Создание хэша хэшей для определения наибольшего числового значения в рубине - PullRequest
1 голос
/ 17 ноября 2010

У меня есть файл данных, который выглядит следующим образом:

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

Файл данных имеет длину ~ 45 000 строк.

Моя цель - это:

FBpp0070000 acyr193594273 acyr 866
FBpp0070000 bomb193605819 bomb 503
FBpp0070001 acyr193618043 acyr 316
FBpp0070001 bomb193638865 bomb 482
FBpp0070001 locu193695159 locu 220

То есть, хранить только те строки с наивысшей оценкой в ​​столбце 4, для каждого другого значения в столбце 3, для каждого значения в столбце 1.

Кроме того, я вижу следующие проблемы: 1) множественные, повторяющиеся «ключи» в столбце 1 и 2) равные «баллы» в столбце 4; Я хочу сохранить только один экземпляр этого дубликата "партитуры".

В прошлом я создавал хеш в perl, который может обрабатывать несколько дублирующихся ключей.

Вот что у меня есть в 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

Итак, я надеюсь, что кто-то может помочь мне определить 1) действительно ли я поступаю правильно и 2) если да, как извлечь нужные мне строки.

Спасибо.

1 Ответ

3 голосов
/ 17 ноября 2010

Следующее, кажется, делает то, что вы хотите, учитывая приведенный выше пример ввода. Вам нужно будет прибегнуть к данным в конце, чтобы получить желаемый формат вывода.

#!/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

Это дает:

dj2@Magnus:~/Development/test $ ./out.rb 
{"FBpp0070000"=>
  {"bomb"=>[503, "bomb193605819"], "acyr"=>[866, "acyr193594273"]},
 "FBpp0070001"=>
  {"bomb"=>[482, "bomb193638865"],
   "locu"=>[220, "locu193695159"],
   "acyr"=>[316, "acyr193618043"]}}
...