Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Array#uniq, не работает Array#uniq 
V
    Опции темы
valodzka
Дата 10.11.2006, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 10.11.2006

Репутация: нет
Всего: нет



Почему неправильно работает этот код? 
Код

irb(main):019:0> [{1=>1}, {1=>1}].uniq
=> [{1=>1}, {1=>1}]

PM   Вверх
setq
Дата 11.11.2006, 10:08 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Может быть он использует проверку .equal? ?
  Вверх
Pete
Дата 11.11.2006, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: 2
Всего: 12



Код

D:\Work>irb
irb(main):001:0> a = [ 1, 1 ]
=> [1, 1]
irb(main):002:0> p a[0].object_id, a[1].object_id
3
3
=> nil
irb(main):003:0> a = [ {1 => 1}, {1 => 1} ]
=> [{1=>1}, {1=>1}]
irb(main):004:0> p a[0].object_id, a[1].object_id
23577508
23577496
=> nil
irb(main):005:0>



--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
FunnyFalcon
Дата 13.11.2006, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 27.3.2006

Репутация: 3
Всего: 7



Вопрос остаётся открытым!!!
Код

yura@falcon:~$ irb
irb(main):001:0> a = [ 1, 1 ]
=> [1, 1]
irb(main):002:0> p a[0].object_id, a[1].object_id
3
3
=> nil
irb(main):003:0> a = [ [1 , 2], [1 , 2] ]
=> [[1, 2], [1, 2]]
irb(main):004:0> p a[0].object_id, a[1].object_id
23577508
23577496
=> nil
irb(main):005:0> a.uniq
=> [[1, 2]]
irb(main):006:0> a = [ {1 , 2}, {1 , 2} ]
=> [{1=>2}, {1=>2}]
irb(main):007:0> a.uniq
=> [{1=>2}, {1=>2}]


Добавлено @ 13:14 
Array вычисляет хэш от аргументов.
Hash возвращяет object_id  smile 
Код

yura@falcon:~/Programming/Ruby/ruby-1.8.5$ irb
irb(main):001:0> [1, 2].hash
=> 11
irb(main):002:0> [[1, 2],[1, 2]].map{|a| a.hash}
=> [11, 11]
irb(main):003:0> [{1, 2},{1, 2}].map{|a| a.hash}
=> [-605969496, -605969506]
irb(main):004:0>


Это сообщение отредактировал(а) FunnyFalcon - 13.11.2006, 13:09
PM MAIL   Вверх
Bikutoru
Дата 16.11.2006, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлекающийся
**


Профиль
Группа: Участник
Сообщений: 522
Регистрация: 24.5.2005
Где: Москва

Репутация: нет
Всего: 22



А как вам такое решение?
Код

class Hash
  def eql?(obj)
    size == keys.find_all { |key| self[key] == obj[key] }.size
  end

  def hash
    all_hashes = []
    ObjectSpace.each_object(Hash) { |obj| all_hashes << obj }
    all_hashes.sort { |a, b| a.object_id <=> b.object_id }.each do |obj|
      return obj.object_id if eql? obj
    end

    object_id
  end
end

puts [{}, {}].uniq.size # 1
puts [{"abc" => 2, 1 => 3}, {1 => 3, "abc" => 2}].uniq.size # 1
puts [{:a => 1}, {:a => 1}, {"b" => 123}].uniq.size # 2


Добавлено @ 12:58 
Хотя, наверное, проще будет написать свой uniq...


--------------------
Человек, словно в зеркале мир — многолик, 
Он ничтожен — и он же безмерно велик!
Омар Хайям
PM   Вверх
FunnyFalcon
Дата 16.11.2006, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 27.3.2006

Репутация: 3
Всего: 7



Вариант
Код

class Hash
  alias eql? :==
  def hash
     to_a.sort! do |a,b|
          a, b  = a[0], b[0]
          a<=>b || a.class <=> b.class || a.class.object_id <=> b.class.object_id
          # Сортировка аля Python.
     end.hash
  end
end


PM MAIL   Вверх
Rubynovich
Дата 18.11.2006, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 7.6.2006

Репутация: 3
Всего: 3



Код

[{1=>1}, {1=>1}].map{ |hash| hash.to_a[0] }.uniq.map{ |array| Hash[ *array ] }

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

Это сообщение отредактировал(а) Rubynovich - 18.11.2006, 14:13
PM MAIL   Вверх
valodzka
Дата 22.11.2006, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 10.11.2006

Репутация: нет
Всего: нет



Цитата(Rubynovich @ 18.11.2006,  14:11)
А вообще, задача немножко бредовая... смущают меня эти пары аля хеш... Уникальность для хешей... странно это все как-то...

Если интересно зачем это реализовывалось: программка осуществляет логический вывод по аналогии, результат хранится ввиде хэша {Переменная=>Константа*}, по ходу вывода возникают несколько результатов, но некоторые могут совпадать. Быстро удалить не получилось, пришлось реализовывать свой uniq. Но уже просто интересно стало что за ерунда.

PM   Вверх
Rubynovich
Дата 26.11.2006, 22:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 7.6.2006

Репутация: 3
Всего: 3



valodzka, метод .uniq для хеш -- это носенс. В нем и так все ключи должны быть уникальными. А задача, которую вы решаете, делается методом .update.
PM MAIL   Вверх
valodzka
Дата 27.11.2006, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 10.11.2006

Репутация: нет
Всего: нет



Цитата(Rubynovich @ 26.11.2006,  22:48)
valodzka, метод .uniq для хеш -- это носенс. В нем и так все ключи должны быть уникальными. А задача, которую вы решаете, делается методом .update.

Непонял...

.uniq это для массива хешей, в котором могут содержаться абсолютно одинаковые  хэши. И чем здесь мог момочь .update? 
PM   Вверх
V.A.KeRneL
  Дата 10.12.2006, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vadim A. Kazantsev
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 3.12.2006
Где: Moscow, Russia

Репутация: 1
Всего: 14



Цитата(FunnyFalcon @ 16.11.2006,  22:43)

Вариант
Код

class Hash
  alias eql? :==
  def hash
     to_a.sort! do |a,b|
          a, b  = a[0], b[0]
          a<=>b || a.class <=> b.class || a.class.object_id <=> b.class.object_id
          # Сортировка аля Python.
     end.hash
  end
end


Спасибо за вариант, FunnyFalcon.
Насколько я понял, Вы программист на Python. И в мире Ruby относительный новичок. Посему позволю себе Вас поправить.

Ну, во-первых, это как-то странно: 
Код

a, b  = a[0], b[0]

Я понимаю, что переменные `a' и `b' локальные и определены только внутри данного блока кода, да и корректному выполнению метода данное присваивание не помешает, но для меня всё же это сродни присваиванию чего-либо счётчику цикла. Целей для такого присваивания может быть 2: 
1) Меньше работать ручками. Тогда Вы мало что выиграли, нужен больший, больший чем 1 строка, кусок кода.
2) Сделать код более читаемым. Это приемлемо. В таком случае, мне кажется, более правильным тут же локально завести новые переменные. Например: 
Код

k, o  = a[0], b[0]


Во-вторых, с учётом 1-го пункта, строку 
Код

a<=>b || a.class <=> b.class || a.class.object_id

надо переписать так: 
Код

(a<=>b).nonzero? || (a.class <=> b.class).nonzero? || a.class.object_id

, потому что в Ruby 0 -- это истина, как и всё, кроме false и nil.

Ну и последнее, Вы совершенно напрасно использовали метод Array#sort!
Тут, очевидно, подразумевался метод Array#sort
Метод Array#sort! я вообще практически не использую. Его можно использовать только в том случае, если Вы хотите отсортировать какую-то свою ПЕРЕМЕННУЮ-массив: 
Код

arr.sort! { |a, b| conditions... }

И даже тогда лучше это сделать при помощи явного присваивания: 
Код

arr = arr.sort { |a, b| conditions... }

А так все старания по модификации самого объекта тратятся впустую!

Добавлено @ 12:15 
Цитата(FunnyFalcon @ 13.11.2006,  13:09)

Добавлено @ 13:14 
Array вычисляет хэш от аргументов.
Hash возвращяет object_id  smile 
Код

yura@falcon:~/Programming/Ruby/ruby-1.8.5$ irb
irb(main):001:0> [1, 2].hash
=> 11
irb(main):002:0> [[1, 2],[1, 2]].map{|a| a.hash}
=> [11, 11]
irb(main):003:0> [{1, 2},{1, 2}].map{|a| a.hash}
=> [-605969496, -605969506]
irb(main):004:0>


Оу, FunnyFalcon, а я сначала не заметил, что это тоже Вы написали. И в голову не пришло! smile Возможно, придётся взять обратно слова по поводу новичка в Ruby. smile

Единственное, что я здесь не пойму так это: 
Код

=> [-605969496, -605969506]

Отрицательные идентификаторы -- это особенность версии 1.8.5 (у меня 1.8.2 и результаты как у Pete, у него, по-моему, 1.8.4) или сборки под *nix?


Это сообщение отредактировал(а) V_A_KeRneL - 16.12.2006, 01:04


--------------------
«C'est un pense-creux d'ici. C'est le meilleur et le plus irascible homme du monde...» © Ф.М. Достоевский, «Бесы»
---/)/)---(\.../)---(\(\
--(':'=)---(=';'=)---(=':')
(")(")..)-(").--.(")-(..(")(")

PM MAIL IM ICQ AOL YIM MSN   Вверх
V.A.KeRneL
  Дата 11.12.2006, 03:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vadim A. Kazantsev
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 3.12.2006
Где: Moscow, Russia

Репутация: 1
Всего: 14



Кстати, FunnyFalcon, зачем в Вашем решении использовалась сортировка, я так и не понял! smile
Да ещё «аля Python»! smile

Выстраданное решение: 
Код

class Hash
    alias eql? :==
    def hash
        to_a.hash
    end
end

puts [{}, {}].uniq.size # 1
puts [{"abc" => 2, 1 => 3}, {1 => 3, "abc" => 2}].uniq.size # 1
puts [{:a => 1}, {:a => 1}, {"b" => 123}].uniq.size # 2


Добавлено @ 03:13 
В тему: http://blade.nagaokaut.ac.jp/cgi-bin/scat....ruby-talk/16778
Еcть идеи насчёт?..


Это сообщение отредактировал(а) V_A_KeRneL - 16.12.2006, 01:05


--------------------
«C'est un pense-creux d'ici. C'est le meilleur et le plus irascible homme du monde...» © Ф.М. Достоевский, «Бесы»
---/)/)---(\.../)---(\(\
--(':'=)---(=';'=)---(=':')
(")(")..)-(").--.(")-(..(")(")

PM MAIL IM ICQ AOL YIM MSN   Вверх
V.A.KeRneL
  Дата 11.12.2006, 03:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vadim A. Kazantsev
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 3.12.2006
Где: Moscow, Russia

Репутация: 1
Всего: 14



А вообще, о таких интересных вещах неплохо было бы спросить разработчиков... Есть смелые добровольцы с хорошим знанием английского/японского? smile



--------------------
«C'est un pense-creux d'ici. C'est le meilleur et le plus irascible homme du monde...» © Ф.М. Достоевский, «Бесы»
---/)/)---(\.../)---(\(\
--(':'=)---(=';'=)---(=':')
(")(")..)-(").--.(")-(..(")(")

PM MAIL IM ICQ AOL YIM MSN   Вверх
FunnyFalcon
Дата 11.12.2006, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 27.3.2006

Репутация: 3
Всего: 7



Цитата

Код
Код

a<=>b || a.class <=> b.class || a.class.object_id

надо переписать так: 
Код
Код

(a<=>b).nonzero? || (a.class <=> b.class).nonzero? || a.class.object_id

, потому что в Ruby 0 -- это истина, как и всё, кроме false и nil.


Спасибо, вы не правы. Я написал именно то, что хотел:
если два ключа сравнимы, то использовать результат их сравнения, 
иначе (когда a<=>b => nil !!!!), попытаться сравнить их классы,
если и классы не сравнимы, то сравнить классы по object_id.
В Python любые два объекта сравнимы именно по такому алгоритму, даже если они не связанных друг с другом классов.
В Ruby же результат сравнения может быть не определён, если классы сравниваемых объектов отношения друг к другу не имеют.

Цитата

Метод Array#sort! я вообще практически не использую. Его можно использовать только в том случае, если Вы хотите отсортировать какую-то свою ПЕРЕМЕННУЮ-массив


Метод sort! можно применять к любому объекту-массиву, чье состояние до сортировки вас абсолютно не интересует.
В данном случае, массив создается и возвращается методом to_a, поэтому я абсолютно уверен, что этот же объект-массив никто больше
не увидит, и я могу отсортировать его на месте, сэкономив память. 

Впрочем - это дело принципа. Мало ли кто унаследует от Hash и захочет переопределить to_a, чтобы он возвращал кешированное значение. Есть безумцы в этом мире. Если учитывать такую вероятность, то вы абсолютно правы.

Цитата

Код

    def hash
        to_a.hash
    end



Я тоже думал так. Но кто гарантирует, что два хеша с одинаковыми ключами вернут методом to_a массив, в котором ключи будут в одинаковом порядке.
Т.е. Вы уверены, что для двух разных объектов - хешей, содержимое которых {1=>2, "2"=>"1"} метод to_a не вернет два разных массива: 
[[1, 2], ["2", "1"]] и [["2","1"],[1,2]] ?
Я не смотрел исходники реализации хэша в Ruby. И кроме того, существуют и другие реализации Ruby (JRuby например).
По-этому я не уверен, и подозреваю, что в общем случае to_a может вернуть разные массивы для равных хешей, если история их наполнения и изменения была разной!!! Поэтому я и сортирую массив по первому элементу - ключу в хэше.
Но Ruby не позволяет сортировать массив с элементами разных классов - см. выше. По-этому я и сортирую как в Python.
PM MAIL   Вверх
Pete
Дата 13.12.2006, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: 2
Всего: 12



Цитата(V_A_KeRneL @  11.12.2006,  04:45 Найти цитируемый пост)
неплохо было бы спросить разработчиков

Ну, понеслась... А все из-за какого-то простого uniq().
Напомнило тему в разделе Си о проверке числа на четность...

Добавлено @ 00:53 
 smile 


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Ruby: Общие вопросы"
source777
  • С чего начать? начинаем
  • Ссылки на полезные ресурсы смотрим тут
  • Обязательно следуйте правилам Vingrad.
  • Пожалуйста, прочитайте рекомендации по работе в форуме и навигации по Vingrad.
  • Для вставки кодов Ruby используйте тег: [code=ruby]код[/code]. Когда в будущем подсветка синтаксиса для Ruby будет реализована, весь исходных код преобразится.
  • Используйтe чекбокс "Транслит" (возле кнопок кодов), если у Вас нет русских шрифтов.
  • Помните, для каждого вопроса должна быть своя тема.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, source777.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Ruby: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1223 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.