Самый быстрый способ найти количество уникальных элементов в строке - PullRequest
5 голосов
/ 08 августа 2011

Как наилучшим образом найти уникальные элементы в строке?

Пример строки формата

myString = "34345667543"

о / р

  ['3','4','3','5'.....]

Ответы [ 6 ]

13 голосов
/ 09 августа 2011

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

require 'rubygems'
require 'benchmark'
require 'set'

puts "Do the test"

Benchmark.bm(40) do |x|

  STRING_TEST = "26263636362626218118181111232112233"

  x.report("do split and uniq") do
    (1..1000000).each { STRING_TEST.split(//).uniq }
  end

  x.report("do chars to_a uniq") do
    (1..1000000).each { STRING_TEST.chars.to_a.uniq }
  end

  x.report("using Set") do
    (1..1000000).each { Set.new(STRING_TEST.split('')).to_a }
  end

end

, и результаты этого теста неудивительны (0n 1.8.7p352):

                                              user     system      total        real
do split and uniq                        27.060000   0.000000  27.060000 ( 27.084629)
do chars to_a uniq                       14.440000   0.000000  14.440000 ( 14.452377)
using Set                                41.740000   0.000000  41.740000 ( 41.760313)

и 1.9.2p180:

                                              user     system      total        real
do split and uniq                        19.260000   0.000000  19.260000 ( 19.242727)
do chars to_a uniq                        8.980000   0.010000   8.990000 (  8.983891)
using Set                                28.220000   0.000000  28.220000 ( 28.186787)

Результаты для REE (1.8.7) близки к 1.9.2:

                                              user     system      total        real
do split and uniq                        19.120000   0.000000  19.120000 ( 19.126034)
do chars to_a uniq                       14.740000   0.010000  14.750000 ( 14.766540)
using Set                                32.770000   0.120000  32.890000 ( 32.921878)

Ради интереса я тоже примерял Рубиниус:

                                              user     system      total        real
do split and uniq                        26.100000   0.000000  26.100000 ( 26.651468)
do chars to_a uniq                       25.680000   0.000000  25.680000 ( 25.780944)
using Set                                22.500000   0.000000  22.500000 ( 22.649291)

Таким образом, хотя split('\\').uniq набирает очки за удобочитаемость, chars.to_a.uniq почти в два раза быстрее.

Странно замечать, что на Рубиниусе решение Set является самым быстрым, но далеко не так быстро, как chars.to_a.uniq на 1.9.2.

8 голосов
/ 08 августа 2011

Используйте этот короткий:

myString.split(//).uniq
6 голосов
/ 08 августа 2011
>> "34345667543".chars.uniq
=> ["3", "4", "5", "6", "7"]
1 голос
/ 30 января 2013
Set.new("34345667543".chars)

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

Это отсутствует в тесте выше и является вторым быстрым в моих тестахс 1.9.3-p274 (самый быстрый - chars.to_a.uniq).Хотя мы все еще говорим о микробенчмарках, в приложении это вряд ли имеет значение:)

1 голос
/ 08 августа 2011

Просто используйте метод разделения:

"12345".split("")
0 голосов
/ 08 августа 2011

Возьмите символы из строки и создайте из них Set:

irb(main):001:0> require 'set'
irb(main):002:0> Set.new("123444454321".split(''))
=> #<Set: {"1", "2", "3", "4", "5"}>

Вызов .split('') просто разбивает строку на массив по символам.Первоначально я использовал String#each_char, но это было впервые в 1.8.7, и вы не упомянули, какую версию Ruby вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...