Каков наилучший способ разбить строку, чтобы получить все подстроки по Ruby? - PullRequest
9 голосов
/ 22 декабря 2010

Например, слова «стек», я хочу получить массив, как:

['s', 'st', 'sta', ... 'stack', 't', 'ta', ... , 'c', 'ck', 'k']

Я сделал это с помощью такого кода:

def split_word(str)
  result = []
  chas = str.split("")
  len = chas.size
  (0..len-1).each do |i|
    (i..len-1).each do |j|
      result.push(chas[i..j].join)
    end
  end
  result.uniq
end

Есть ли лучший и чистый способ сделать это? Спасибо.

Ответы [ 6 ]

11 голосов
/ 22 декабря 2010
def split_word s
  (0..s.length).inject([]){|ai,i|
    (1..s.length - i).inject(ai){|aj,j|
      aj << s[i,j]
    }
  }.uniq
end

И вы также можете рассмотреть возможность использования Set вместо массива для результата.

PS: Вот еще одна идея, основанная на массиве product:

def split_word s
  indices = (0...s.length).to_a
  indices.product(indices).reject{|i,j| i > j}.map{|i,j| s[i..j]}.uniq
end
5 голосов
/ 22 декабря 2010

Я бы написал:

def split_word(s)
  0.upto(s.length - 1).flat_map do |start| 
    1.upto(s.length - start).map do |length| 
      s[start, length]
    end
  end.uniq
end

groups = split_word("stack")
# ["s", "st", "sta", "stac", "stack", "t", "ta", "tac", "tack", "a", "ac", "ack", "c", "ck", "k"]

Обычно более понятно и более компактно использовать map (функциональный) вместо шаблона init empty + каждый + append + return (императив).

3 голосов
/ 10 июля 2013
def substrings(str)
  output = []
  (0...str.length).each do |i|
    (i...str.length).each do |j|
      output << str[i..j]
    end
  end
  output
end

это просто очищенная версия вашего метода, и она работает с меньшим количеством шагов =)

3 голосов
/ 22 декабря 2010

Не думаю.

Вот моя попытанная версия:

def split_word(str)
  length = str.length - 1
  [].tap do |result|
    0.upto(length) do |i|
      length.downto(i) do |j|
        substring = str[i..j]
        result << substring unless result.include?(substring)
      end
    end
  end
end
2 голосов
/ 30 октября 2013
def substrings(str)
  (0...str.length).map do |i|
     (i...str.length).each { |j| str[i..j]}
  end
end

Еще один способ сделать это, который мне немного понятнее.

0 голосов
/ 12 мая 2013

Путь позже, но это то, что я получил от небольшого переформатирования вашего кода.

def substrings(string)
  siz = string.length
  answer = []

  (0..siz-1).each do |n|
    (n..siz-1).each do |i|
      answer << string[n..i]
    end
  end
  answer
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...