If I have a string such as 'abcde' and I want to get a 2d array of all combinations of 1 or 2 letters.
[ ['a', 'b', 'c', 'd', 'e'], ['ab', 'c', 'de'], ['a', 'bc', 'd', 'e'] ...
How would I go abouts doing so?
I want to do this in ruby, and think I should be using a regex. I've tried using
strn = 'abcde'
strn.scan(/[a-z][a-z]/)
but this is only going to give me the distinct sets of 2 characters
['ab', 'cd']
I think this should do it (haven't tested yet):
def find_letter_combinations(str)
return [[]] if str.empty?
combinations = []
find_letter_combinations(str[1..-1]).each do |c|
combinations << c.unshift(str[0])
end
return combinations if str.length == 1
find_letter_combinations(str[2..-1]).each do |c|
combinations << c.unshift(str[0..1])
end
combinations
end
Regular expressions will not help for this sort of problem. I suggest using the handy Array#combination(n)
function in Ruby 1.9:
def each_letter_and_pair(s)
letters = s.split('')
letters.combination(1).to_a + letters.combination(2).to_a
end
ss = each_letter_and_pair('abcde')
ss # => [["a"], ["b"], ["c"], ["d"], ["e"], ["a", "b"], ["a", "c"], ["a", "d"], ["a", "e"], ["b", "c"], ["b", "d"], ["b", "e"], ["c", "d"], ["c", "e"], ["d", "e"]]
No, regex is not suitable here. Sure you can match either one or two chars like this:
strn.scan(/[a-z][a-z]?/)
# matches: ['ab', 'cd', 'e']
but you can't use regex to generate a (2d) list of all combinations.
A functional recursive approach:
def get_combinations(xs, lengths)
return [[]] if xs.empty?
lengths.take(xs.size).flat_map do |n|
get_combinations(xs.drop(n), lengths).map { |ys| [xs.take(n).join] + ys }
end
end
get_combinations("abcde".chars.to_a, [1, 2])
#=> [["a", "b", "c", "d", "e"], ["a", "b", "c", "de"],
# ["a", "b", "cd", "e"], ["a", "bc", "d", "e"],
# ["a", "bc", "de"], ["ab", "c", "d", "e"],
# ["ab", "c", "de"], ["ab", "cd", "e"]]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.