Could you help me?
I need a regex that splits strings like
"11231114"
to
['11', '2', '3', '111', '4']
You could implement String#scan as follows:
"11231114".scan(/((\d)\2*)/).map(&:first)
#=> ["11", "2", "3", "111", "4"]
You could pass a block to String#scan pushing the match group to an array.
matches = []
"11231114".scan(/((\d)\2*)/) do |n,r| matches << n end
In Javascript you can do:
var m = "11231114".match(/(\d)\1*/g)
//=> ["11", "2", "3", "111", "4"]
You can use similar approach in whatever language/tool you're using.
Approach is to capture a digit using (\d) and then match all the back-references for the same using \1*.
You could do something like this,
> str = "11231114"
=> "11231114"
> str1 = str.gsub(/(?<=(\d))(?!\1)/, "*")
=> "11*2*3*111*4*"
> str1.split('*')
=> ["11", "2", "3", "111", "4"]
There is slice_when in Ruby 2.2:
"11231114".chars.slice_when { |x, y| x != y }.map(&:join)
Related
A similar question has been answered here However I'd like to know how I can add up/group the numbers from one array based on the duplicate values of another array.
test_names = ["TEST1", "TEST1", "TEST2", "TEST3", "TEST2", "TEST4", "TEST4", "TEST4"]
numbers = ["5", "4", "3", "2", "9", "7", "6", "1"]
The ideal result I'd like to get is a hash or an array with:
{"TEST1" => 9, "TEST2" => 12, "TEST3" => 2, "TEST4" => 14}
Another way I found you can do:
test_names.zip(numbers).each_with_object(Hash.new(0)) {
|arr, hsh| hsh[arr[0]] += arr[1].to_i }
You can do it like this:
my_hash = Hash.new(0)
test_names.each_with_index {|name, index| my_hash[name] += numbers[index].to_i}
my_hash
#=> {"TEST1"=>9, "TEST2"=>12, "TEST3"=>2, "TEST4"=>14}
I wish to follow #squidguy's example and use Enumerable#zip, but with a different twist:
{}.tap { |h| test_names.zip(numbers.map(&:to_i)) { |a|
h.update([a].to_h) { |_,o,n| o+n } } }
#=> {"TEST1"=>9, "TEST2"=>12, "TEST3"=>2, "TEST4"=>14}
Object#tap is here just a substitute for Enumerable#each_with_object or for having h={} initially and a last line with just h.
I'm using the form of Hash#update (aka merge!) that takes a block for determining the merged value for each key that is present in both the original hash (h) and the hash being merged ([a].to_h). There are three block variables, the shared key (which we don't use here, so I've replaced it with the placeholder _), and the values for that key for the original hash (o) and for the hash being merged (n).
I am trying to create an array that shows every digit permutation of a given number input. With a given input "123", the array should look like this:
["123", "132", "213", "231", "312", "321"]
I can get an array containing arrays of the separate digits:
a = []
"123".split('').each {|n| a.push(n) }
arraycombinations = a.permutation(a.length).to_a
# => [["1", "2", "3"], ["1", "3", "2"], ["2", "1", "3"], ["2", "3", "1"], ["3", "1", "2"], ["3", "2", "1"]]
but I cannot figure out how to join the second or third dimensions of arraycombinations while preserving the first dimension.
Each of these attempts failed:
arraycombinations.map {|x| print arraycombinations.join("") }
arraycombinations.map {|ar| ar.split(",") }
arraycombinations.each {|index| arraycombinations(index).join("") }
How can I isolate the join function to apply to only the second dimension within a multidimensional array?
Assuming you already have an array of arrays such as
a = [["1","2","3"],["1","3","2"],["2","1","3"],["2","3","1"], ["3","1","2"],["3","2","1"]]
a.map { |i| i.join}
#=>["123", "132", "213", "231", "312", "321"]
It's simple really
"123".split("").permutation.to_a.map { |x| x.join }
Let me explain a bit:
"123".split("") gives you an array ["1","2","3"]
permutation.to_a gives you array of arrays [["1","2","3"], ["2","1","3"] ... ]
then you must join each of those arrays inside with map { |x| x.join }
and you get the required end result.
Like this:
arraycombinations.map(&:join)
# => ["123", "132", "213", "231", "312", "321"]
My array is ["Mehmet,1,3,0,0,0\n", "Veli,2,1,2,0,2\n", "Ali,0,1,1,0,0\n"].
I want to declare two dimensional array like array[1][2] with first dimension for name and second one for note.
How can I make it?
Text.txt is
Mehmet,1,3,0,0,0
Veli,2,1,2,0,2
Ali,0,1,1,0,0
My code is
filename = "text.txt"
results = []
File.new(filename, "r").each { |line| results << line }
results.inject([]){|ar,s|
ar.concat(s.split(/,/))}
puts results.inspect
To modify the set that you first posted:
data = ["Mehmet,1,3,0,0,0\n", "Veli,2,1,2,0,2\n", "Ali,0,1,1,0,0\n"]
data = data.map {|x| y = x.split(","); [y.delete_at(0), y] }
=> [["Mehmet", ["1", "3", "0", "0", "0\n"]],
["Veli", ["2", "1", "2", "0", "2\n"]],
["Ali", ["0", "1", "1", "0", "0\n"]]]
puts data[0][0]
=> Mehmet
array = File.read("text.txt").split
# => ["Mehmet,1,3,0,0,0", "Veli,2,1,2,0,2", "Ali,0,1,1,0,0"]
array.map { |ar| x, *xs = ar.split(","); [x, xs.join] }
# => [["Mehmet", "13000"], ["Veli", "21202"], ["Ali", "01100"]]
Or, if you don't want to join the second sub-array
array.map { |ar| x, *xs = ar.split(","); [x, xs] }
# => [["Mehmet", ["1", "3", "0", "0", "0"]],
# ["Veli", ["2", "1", "2", "0", "2"]],
# ["Ali", ["0", "1", "1", "0", "0"]]]
2d array means array of arrays. So, simply it can be like:
board = [ [ 1, 2, 3 ],[ 4, 5, 6 ]]
Are you looking for something like this?
array = ["Mehmet,1,3,0,0,0\n", "Veli,2,1,2,0,2\n", "Ali,0,1,1,0,0\n"]
new_array = array.map do |elem|
splited = elem.split(/[,\s]/)
[splited.shift, splited]
end
# => [["Mehmet", ["1", "3", "0", "0", "0"]],
# ["Veli", ["2", "1", "2", "0", "2"]],
# ["Ali", ["0", "1", "1", "0", "0"]]]
I have string like this: "1112222355". How can I get array like that ["111","2222","3","55"] using Ruby?
Assuming you want to group only consecutive elements, use Enumerable#chunk:
> "1112222355".chars.chunk { |x| x }.map { |c, cs| cs.join }
=> ["111", "2222", "3", "55"]
"1112222355".scan(/((.)\2*)/).map(&:first)
# => ["111", "2222", "3", "55"]
I've this familiar question that looks like permutation/combination of the Math world.
How can I achieve the following via ruby?
badges = "1-2-3"
badge_cascade = []
badges.split("-").each do |b|
badge_cascade << b
end
Gives: => ["1", "2", "3"]
But I want it to be is:
=> ["1", "2", "3",
"1-2", "2-3", "3-1", "2-1", "3-2", "1-3",
"1-2-3", "2-3-1", "3-1-2"]
Functional approach:
bs = "1-2-3".split("-")
strings = 1.upto(bs.size).flat_map do |n|
bs.permutation(n).map { |vs| vs.join("-") }
end
#=> ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
You ned to use Array#permutation method in order to get all permutations:
arr = "1-2-3".split '-' # => ["1", "2", "3"]
res = (1..arr.length).reduce([]) { |res, length|
res += arr.permutation(length).to_a
}.map {|arr| arr.join('-')}
puts res.inspect
# => ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
Let me explain the code:
You split string into array passing separator '-' to String#split method
You need all permutations of length 1, 2, 3. Range 1..arr.length represents all these lengths.
You collect an array of all permutations using Enumerable#reduce.
You will get array of arrays here:
[["1"], ["2"], ["3"], ["1", "2"], ["1", "3"], ["2", "1"], ["2", "3"], ["3", "1"], ["3", "2"], ["1", "2", "3"], ["1", "3", "2"], ["2", "1", "3"], ["2", "3", "1"], ["3", "1", "2"], ["3", "2", "1"]]
You transform all subarrays of this array into strings using Array#join with your '-' separator inside of Enumerable#map
Array#permutation(n) will give you all the permutations of length n as an Array of Arrays so you can call this with each length between 1 and the number of digits in badges. The final step is to map these all back into strings delimited with -.
badges = "1-2-3"
badges_split = badges.split('-')
permutations = []
(1..badges_split.size).each do |n|
permutations += badges_split.permutation(n).to_a
end
result = permutations.map { |permutation| permutation.join('-') }
Update: I think Alex's use of reduce is a more elegant approach but I'll leave this answer here for now in case it is useful.