2016-02-22 4 views
0

У меня есть текстовый файл с двумя столбцами. Значения в первом столбце («ключ») различны, значения во втором столбце - эти строки имеют длину от 10 до примерно 200 - имеют несколько дубликатов. Количество дубликатов варьируется. Некоторые строки - особенно более длинные - не имеют дубликатов, в то время как другие могут иметь 20 дублирующих ситуаций.Ruby: Оптимизация хранения для хранения большого количества строк, некоторые из них дубликаты

key1 valueX 
key2 valueY 
key3 valueX 
key4 valueZ 

Я хотел бы представить эти данные как хэш. Из-за большого количества ключей и наличия повторяющихся значений мне интересно, поможет ли какой-то метод совместного использования общих строк.

Данные в файле являются «постоянными», т. Е. Я могу приложить усилия (в промежуток времени) для предварительной обработки его подходящим способом, при условии, что он будет доступен эффективно, как только он будет введен в мое приложение.

Теперь я опишу алгоритм, где, я считаю, это решит проблему. Мой вопрос:, является ли алгоритм звуковым, соответственно, можно ли его улучшить. Кроме того, я хотел бы знать, является ли с помощью freeze на струнах обеспечит дополнительную оптимизацию:

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

key1 valueX 
key2 valueY 
key3 valueX key1 
key4 valueZ 

Когда я прочитал в моем приложении данных в память (строка по строке), я использую эту аннотацию, чтобы создать указатель на исходную строку, в вместо размещения нового:

if columns.size == 3 
    myHash[columns[0]] = columns[1] # First occurance of the string 
else 
    myHash[columns[0]] = myHash[columns[2]].dup # Subsequent occurances 
end 

Достигнуто ли мое достижение? Можно ли это сделать лучше?

+3

Почему, на ваш взгляд, это достигает вашей цели? вы создаете дубликат дублированного значения - это означает, что вы удерживаете его дважды в памяти ... похоже, что это чрезмерный избыток - есть ли у вас настоящая проблема или вы оптимизируете досрочно? –

+3

Ваш вопрос, кажется, «Мне интересно, поможет ли какой-то способ совместного использования общих строк». Нам не дана ваша «цель». Если бы мы были, у нас не было бы критериев, чтобы определить, было ли это достигнуто (если это не субъективно, нет - нет для вопросов SO). –

+0

@UriAgassi: Это 'dup', а не' clone'. Это гарантирует, что присутствует только одна копия строки.И, учитывая огромное количество строк, я не думаю, что это досрочно, но, кроме этого, меня тоже интересует сама проблема. – user1934428

ответ

0

Один из способов сделать это - использовать символы.

["a", "b", "c", "a", "d", "c"].each do |c| 
    puts c.intern.object_id 
end 

417768 #a 
313128 #b 
312328 #c 
417768 #a 
433128 #d 
312328 #c 

Обратите внимание, что c имеет такое же значение.

Вы можете превратить строку в символ с помощью метода intern. Если вы ставите равную строку, вы должны получить один и тот же символ, например, flyweight pattern.

Если вы сохраните символ в своем хеше, у вас будет только одна строка за один раз. Когда пришло время использовать символ, просто вызовите .to_s на символ, и вы вернете строку обратно. (Не знаю, как работает to_s, он может выполнять работу по созданию каждого вызова.) Еще одна идея - кэшировать строки самостоятельно, т. Е. Иметь целое число для хэш-кода кеша и просто поместить целочисленный ключ в ваши структуры данных. Когда вам нужна строка, вы можете ее найти.

+0

Что касается 'intern': @UriAgassi также предложил это в своем комментарии. Я исследую это. Верно, что 'to_s' воссоздает строку, но это только одна строка за раз (во время обработки), и память снова исправляется. Кроме того, не все строки действительно «используются» для сравнения во время каждого прогона. – user1934428

+0

Использование целочисленного ключа является концептуально хорошей идеей, но, возможно, необязательно, если я храню ссылку на объект на строку. Возможно, я ошибался в использовании 'dup' (см. Мои другие комментарии к этой теме), и просто« переназначение существующей строки »точно достигнет моей цели. – user1934428

Смежные вопросы