Вставка в Set, изменяющая порядок элементов в массиве в Ruby - PullRequest
0 голосов
/ 05 февраля 2009
@search_results = Array.new
duplicates = Set.new
results.each { |result|    @search_results.push(result) unless duplicates.add?(result[:url]) }

Этот фрагмент кода искажает порядок элементов в массиве @search_results. Зачем вставка одного и того же элемента в набор и массив меняет порядок вставки для массива? Похоже, некоторые проблемы со ссылками на элементы. Может кто-нибудь объяснить?

Редактировать 1: Я использую массив. Извините за более раннюю опечатку. Я дважды проверил по коду, и он тоже использует массив (в любом случае для Hash нет метода push)

Ответы [ 2 ]

2 голосов
/ 05 февраля 2009

Порядок элементов в хэше не гарантируется. Вам придется отсортировать ключи, если вы хотите гарантированный заказ.

Якобы это исправлено в Ruby 1.9.

Редактировать: Я предполагаю, что ваши результаты представлены в массиве, если порядок хэшей не гарантирован, и вам придется сортировать ключи, вот как выглядит мой тест:

#!/usr/bin/ruby -W

require 'pp'
require 'set'

results = Array.new

results << {:url => 'http://lifehacker.com'}
results << {:url => 'http://stackoverflow.com'}
results << {:url => 'http://43folders.com'}
results << {:url => 'http://lolindrath.com'}
results << {:url => 'http://stackoverflow.com'}
results << {:url => 'http://lifehacker.com'}



@search_results = Array.new
duplicates = Set.new

results.each { |result| @search_results.push(result) unless duplicates.add?(result[:url])}

puts "## @search_results"
pp @search_results

Если я выполню это, вот результат:

## @search_results
[{:url=>"http://stackoverflow.com"}, {:url=>"http://lifehacker.com"}]

Я обнаружил, что это странно, поэтому, чтобы быть уверенным, я поставил .nil? добавить конец .add? и вот мой результат:

## @search_results
[{:url=>"http://lifehacker.com"},
 {:url=>"http://stackoverflow.com"},
 {:url=>"http://43folders.com"},
 {:url=>"http://lolindrath.com"}]

Теперь , что было тем, что я ожидал: это то, что вы подразумеваете под "искаженным"?

Редактировать 2: После дальнейших исследований, я думаю, это из-за очень строгих правил Руби при преобразовании небулевых данных в логические (см. Ruby Gotchas в Википедии и Переполнение стека, конечно ), так что все, что только ложно, действительно ложно, а все остальное верно. поэтому .nil? явно преобразует его в true / false.

irb(main):007:0> puts "zero is true" if 0
zero is true
=> nil
irb(main):008:0> puts "zero is false" unless 0
=> nil
0 голосов
/ 05 февраля 2009

искажен как? Что за объект results? Если results является Set или Hash, то вам не гарантируется, что любые два обхода results будут в одном порядке.

Кроме того, вы могли бы сделать

@search_results = results.uniq

, если results - это Array, чтобы получить все уникальные результаты.

------------------------------------------------------------- Array#uniq
     array.uniq   -> an_array
------------------------------------------------------------------------
     Returns a new array by removing duplicate values in self.

        a = [ "a", "a", "b", "b", "c" ]
        a.uniq   #=> ["a", "b", "c"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...