Costruire un hash di hash per determinare il più grande valore numerico in Ruby
-
25-09-2019 - |
Domanda
Ho un file di dati che assomiglia a questo:
FBpp0070000 acyr193594273 acyr 866
FBpp0070000 acyr193577824 acyr 536
FBpp0070000 acyr193693009 acyr 445
FBpp0070000 bomb193605819 bomb 503
FBpp0070000 bomb193676398 bomb 101
FBpp0070001 acyr193618043 acyr 316
FBpp0070001 acyr193617997 acyr 313
FBpp0070001 bomb193638865 bomb 482
FBpp0070001 locu193695159 locu 220
FBpp0070001 locu193638863 locu 220
Il file di dati è lungo ~ 45.000 righe.
Il mio obiettivo è avere questo:
FBpp0070000 acyr193594273 acyr 866
FBpp0070000 bomb193605819 bomb 503
FBpp0070001 acyr193618043 acyr 316
FBpp0070001 bomb193638865 bomb 482
FBpp0070001 locu193695159 locu 220
Vale a dire, conservare solo quelle linee con il punteggio più alto nella colonna 4, per ogni valore diverso nella colonna 3, per ciascun valore nella colonna 1.
Inoltre, i problemi che sto vedendo sono 1) "tasti" multipli e duplicati nei punteggi uguali della colonna 1 e 2) nella colonna 4; Voglio conservare solo un'istanza di quel duplicato "punteggio".
In passato ho costruito un hash in perl in grado di gestire più chiavi duplicate.
Ecco cosa ho finora in Ruby.
hash = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) }
title = ''
File.open('test1.txt', 'r').each do |line|
line.chomp!
query, hit, taxa, score = line.split(/\s/)
hash[query][hit][taxa] = score
# end
#p "#{query}: #{taxa}: #{score}"
end
p hash
Quindi, spero che qualcuno possa aiutarmi a determinare 1) se, in effetti, lo faccio correttamente e 2) in tal caso, come estrarre le linee di cui ho bisogno.
Grazie.
Soluzione
Quanto segue sembra fare quello che vuoi, dato l'esempio di input che hai dato sopra. Dovrai ricorrere ai dati alla fine per ottenere il formato di output che desideri.
#!/usr/bin/env ruby
require 'pp'
data = {}
File.open("input.txt", "r").each do |l|
l.chomp!
query, hit, taxa, score = l.split(/\s+/)
data[query] ||= {}
data[query][taxa] ||= [0, nil]
data[query][taxa] = [score.to_i, hit] if score.to_i > data[query][taxa].first
end
pp data
Questo da:
dj2@Magnus:~/Development/test $ ./out.rb
{"FBpp0070000"=>
{"bomb"=>[503, "bomb193605819"], "acyr"=>[866, "acyr193594273"]},
"FBpp0070001"=>
{"bomb"=>[482, "bomb193638865"],
"locu"=>[220, "locu193695159"],
"acyr"=>[316, "acyr193618043"]}}