2009-02-05 3 views
0
@search_results = Array.new 
duplicates = Set.new 
results.each { |result| @search_results.push(result) unless duplicates.add?(result[:url]) } 

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

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

+0

Откуда берутся переменные «результаты»? Может быть, его порядок неопределен (например, если это хэш или набор). – Chuck

+0

Пожалуйста, определите 'garbled': какой порядок вы ожидаете от них? Как изменился порядок? – Lolindrath

+0

@chuck - результаты - это массив. @Lolindrath - Я ожидаю, что порядок будет таким же, как и порядок его вставки. Вместо этого он дает случайный порядок. – Sanjay

ответ

2

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

Это, предположительно, исправлено в Ruby 1.9, я считаю.

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

#!/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"}] 

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

Edit 2: При дальнейшем расследовании, я думаю, что это из-за супер строгих правил Руби при преобразовании без логических данных в булевы (см Ruby Gotchas on Wikipedia и Stack Overflow, of course), так что в основном все, что только ложь на самом деле ложь, и все остальное правда. поэтому .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

См. Мое редактирование. Это была опечатка – Sanjay

+0

Да, это именно то, что я имел в виду. Довольно странно, что добавление .nil? заставляет его работать. – Sanjay

+0

Вопрос в том, что .add?возвращает nil на SUCCESS и объект на FAILURE, поэтому вы тестировали условие восстановления, так как nil ложно в Ruby – rampion

0

Garbled how? Какой объект 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"] 
+0

См. мое редактирование. Это была опечатка – Sanjay

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

  • Нет связанных вопросов^_^