Script on hash sort - is it possible to optimize?

I wrote a ruby script hash sort related, but feel it’s not good, is it
possible to optimize?

==========================================
There is a string(“string_sample”, every line end with “\n”),
I want the strings sort by user names with the licenses number used.(If
line without license number, then license number=1)
example: User name1 use 1(string_sample line1) + 2(string_sample line4)
, total 3 licenses

string_sample = " name1 machin1 NoXDisplay (v2012.12) (server1/port1
18709), start Fri 1/24 17:26
name2 mchine2 NoXDisplay J3_ffffffffa8c0a600_21848_2 (v2012.12)
(server2/port2 13335), start Fri 1/24 9:29
name2 machine3 NoXDisplay J3_ffffffffa8c0a600_21848_1 (v2012.12)
(server3/port3 8569), start Fri 1/24 9:26
name1 machine4 NoXDisplay (v2012.12) (192.168.0.197/27007 38446),
start Fri 1/24 19:07, 2 licenses
name3 machine5 NoXDisplay (v2012.12) (server4/port4 10195), start
Wed 1/22 10:30
name3 machine6 NoXDisplay J3_ffffffffa8c0a600_21848_3 (v2012.12)
(server5/port5 6975), start Fri 1/24 9:30
name6 machine7 NoXDisplay (v2012.12) (server6/port6 16114), start
Thu 1/23 15:31"

=>

==================
name1(3)

name1 machin1 NoXDisplay (v2012.12) (server1/port1 18709), start Fri

1/24 17:26
name1 machine4 NoXDisplay (v2012.12) (192.168.0.197/27007 38446),
start Fri 1/24 19:07, 2 licenses

name3(2)

name3 machine5 NoXDisplay (v2012.12) (server4/port4 10195), start

Wed 1/22 10:30
name3 machine6 NoXDisplay J3_ffffffffa8c0a600_21848_3 (v2012.12)
(server5/port5 6975), start Fri 1/24 9:30

name2(2)

name2 mchine2 NoXDisplay J3_ffffffffa8c0a600_21848_2 (v2012.12)

(server2/port2 13335), start Fri 1/24 9:29
name2 machine3 NoXDisplay J3_ffffffffa8c0a600_21848_1 (v2012.12)
(server3/port3 8569), start Fri 1/24 9:26

name6(1)

name6 machine7 NoXDisplay (v2012.12) (server6/port6 16114), start

Thu 1/23 15:31

#==========================================
#test.rb
#==========================================
string_sample = " name1 machin1 NoXDisplay (v2012.12) (server1/port1
18709), start Fri 1/24 17:26
name2 mchine2 NoXDisplay J3_ffffffffa8c0a600_21848_2 (v2012.12)
(server2/port2 13335), start Fri 1/24 9:29
name2 machine3 NoXDisplay J3_ffffffffa8c0a600_21848_1 (v2012.12)
(server3/port3 8569), start Fri 1/24 9:26
name1 machine4 NoXDisplay (v2012.12) (192.168.0.197/27007 38446),
start Fri 1/24 19:07, 2 licenses
name3 machine5 NoXDisplay (v2012.12) (server4/port4 10195), start
Wed 1/22 10:30
name3 machine6 NoXDisplay J3_ffffffffa8c0a600_21848_3 (v2012.12)
(server5/port5 6975), start Fri 1/24 9:30
name6 machine7 NoXDisplay (v2012.12) (server6/port6 16114), start
Thu 1/23 15:31"

def check_license_number_each_line(lmstat_line)
lic_used_num_eachline = 0
if lmstat_line =~ /(\d+)\s+licenses/
lic_used_num_eachline = $1.to_i
else
lic_used_num_eachline = 1
end
return lic_used_num_eachline
end

hash_save = Hash.new
string_sample.lines.each do |x|
name = x.split(/\s+/)[1]
if hash_save.include?(name)
hash_save[name] += x
else
hash_save[name] = x
end
end

hash_save.each {|key, value|
account_lic_used = 0
value.each_line {|line|
account_lic_used += check_license_number_each_line(line)
}
hash_save[key] = [value, account_lic_used]
}

a = hash_save.sort_by {|key, value| value[1]}.reverse

puts ‘
puts ‘Sort by license used:’
puts '

a.each {|key, value|
puts ‘==================’
puts “#{key}(#{value[1]})”
puts ‘==================’
puts value[0]
}

On 1/25/14, Previn L. [email protected] wrote:

I wrote a ruby script hash sort related, but feel it’s not good

your code reads fine. and besides, programmers always tend to feel not
*good : )

is it possible to simplify?

possibly. just go slow. sometimes you lose some shortcuts if you’re too
fast.

eg, here is my first shot

def license_cnt line
line =~ /(\d+)\s+licenses/
($1 || 1).to_i
end

hash_names=Hash.new { |hash, key| hash[key] = [[],0] }
lines.each_line {|line|
name, _ = line.split /\s+/, 2
hash_names[name][0] << line
hash_names[name][1] += license_cnt(line)
}

puts ‘
puts ‘Sort by license used:’
puts '

hash_names.
sort_by{|_,v| -v[1]}.
each {|name, value|
puts ‘==================’
puts “#{name} (#{value[1]})”
puts ‘==================’
puts value[0]
}

botp wrote in post #1134375:

def license_cnt line
line =~ /(\d+)\s+licenses/
($1 || 1).to_i
end

hash_names=Hash.new { |hash, key| hash[key] = [[],0] }
lines.each_line {|line|
name, _ = line.split /\s+/, 2
hash_names[name][0] << line
hash_names[name][1] += license_cnt(line)
}

puts ‘
puts ‘Sort by license used:’
puts '

hash_names.
sort_by{|_,v| -v[1]}.
each {|name, value|
puts ‘==================’
puts “#{name} (#{value[1]})”
puts ‘==================’
puts value[0]
}

Dear botp,

I have tested the code, works well, much better than mine, many thanks.

On Sat, Jan 25, 2014 at 9:59 AM, Previn L. [email protected]
wrote:

name3 machine6 NoXDisplay J3_ffffffffa8c0a600_21848_3 (v2012.12)

(server5/port5 6975), start Fri 1/24 9:30
name6 machine7 NoXDisplay (v2012.12) (server6/port6 16114), start
Thu 1/23 15:31"

Hi, this is how I’d do it:

2.0.0p195 :018 > sample = " name1 machin1 NoXDisplay (v2012.12)
(server1/port1 18709), start Fri 1/24 17:26
2.0.0p195 :019"> name2 mchine2 NoXDisplay
J3_ffffffffa8c0a600_21848_2 (v2012.12) (server2/port2 13335), start
Fri 1/24 9:29
2.0.0p195 :020"> name2 machine3 NoXDisplay
J3_ffffffffa8c0a600_21848_1 (v2012.12) (server3/port3 8569), start Fri
1/24 9:26
2.0.0p195 :021"> name1 machine4 NoXDisplay (v2012.12)
(192.168.0.197/27007 38446), start Fri 1/24 19:07, 2 licenses
2.0.0p195 :022"> name3 machine5 NoXDisplay (v2012.12)
(server4/port4 10195), start Wed 1/22 10:30
2.0.0p195 :023"> name3 machine6 NoXDisplay
J3_ffffffffa8c0a600_21848_3 (v2012.12) (server5/port5 6975), start Fri
1/24 9:30
2.0.0p195 :024"> name6 machine7 NoXDisplay (v2012.12)
(server6/port6 16114), start Thu 1/23 15:31"

(I’ve used the rule that when there are licenses in the string, there
are two ‘,’):

2.0.0p195 :038 > licenses = sample.scan(/\s+([^
])[^,],(?:[^,],\s+(\d+) licenses)?.$/)
=> [[“name1”, nil], [“name2”, nil], [“name2”, nil], [“name1”, “2”],
[“name3”, nil], [“name3”, nil], [“name6”, nil]]

The rest is adding together each name and sorting:

2.0.0p195 :039 > h = Hash.new(0)
=> {}
2.0.0p195 :040 > licenses.each {|name, num| h[name] += (num.nil? ? 1 :
num.to_i)}
=> [[“name1”, nil], [“name2”, nil], [“name2”, nil], [“name1”, “2”],
[“name3”, nil], [“name3”, nil], [“name6”, nil]]
2.0.0p195 :041 > h.sort_by {|k,v| -v}
=> [[“name1”, 3], [“name2”, 2], [“name3”, 2], [“name6”, 1]]

Tip: if you want to sort from biggest to smallest, use -v, instead of
sorting and reversing.

Hope this helps,

Jesus.

Jesús Gabriel y Galán wrote in post #1134504:

Hi, this is how I’d do it:

2.0.0p195 :038 > licenses = sample.scan(/\s+([^
])[^,],(?:[^,],\s+(\d+) licenses)?.$/)
=> [[“name1”, nil], [“name2”, nil], [“name2”, nil], [“name1”, “2”],
[“name3”, nil], [“name3”, nil], [“name6”, nil]]

The rest is adding together each name and sorting:

2.0.0p195 :039 > h = Hash.new(0)
=> {}
2.0.0p195 :040 > licenses.each {|name, num| h[name] += (num.nil? ? 1 :
num.to_i)}
=> [[“name1”, nil], [“name2”, nil], [“name2”, nil], [“name1”, “2”],
[“name3”, nil], [“name3”, nil], [“name6”, nil]]
2.0.0p195 :041 > h.sort_by {|k,v| -v}
=> [[“name1”, 3], [“name2”, 2], [“name3”, 2], [“name6”, 1]]

Tip: if you want to sort from biggest to smallest, use -v, instead of
sorting and reversing.

Hope this helps,

Jesus.
Dear Jesus,

This is really helpful, thank you so much!

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs