Remove duplicates conditionally from array in Ruby [duplicate] - ruby

This question already has answers here:
Remove redundant or duplicate tuples in Ruby array
(6 answers)
Closed 9 years ago.
So i have this array:
['One', 'Two', 'One', 'One', 'Three', 'Three', 'One']
I want to get this result:
['One', 'Two', 'One', 'Three', 'One']
So I want to remove items that is the same as previous item.
How to do that in Ruby?

Use Enumerable#chunk
ary = ['One', 'Two', 'One', 'One', 'Three', 'Three', 'One']
ary.chunk {|x| x }.map(&:first)
#=> ["One", "Two", "One", "Three", "One"]
Enumerable#chunk enumerates over the items, chunking them together based on the return value of the block. consecutive elements which return the same block value are chunked together.
ary.chunk {|x| x }.to_a
=> [["One", ["One"]],
["Two", ["Two"]],
["One", ["One", "One"]],
["Three", ["Three", "Three"]],
["One", ["One"]]]
map(&:first) Array#map iterates over the array calling the first method on each element of the array
&:first is called symbol to proc which creates a proc object that map yields each element of the array to
so the example above could be rewritten as below:
lambda_obj = ->(ele) { ele.first }
ary.chunk {|x| x }.map(&lambda_obj)
#=> ["One", "Two", "One", "Three", "One"]

Pretty straightforward with inject:
ary.inject [] do |accum,x|
accum.last == x ? accum : accum << x
end

Related

What is best way to create an array of hashes from an array?

Given this array:
array = ['one', 'two']
what is the best way to turn that into something like the following?
[{value: 'one', label: 'one'}, {value: 'two', label: 'two'}]
Use Array#map, which iterates over your collection and returns an array. In your case, just return the hash directly
array.map { |a| {value: a, label: a} }
# => [{:value=>"one", :label=>"one"}, {:value=>"two", :label=>"two"}]
The best way is Array#map, but just to try a different way check also Enumerable#each_with_object:
array = ['one', 'two']
array.each_with_object([]) { |e, a| a << {value: e, label: e} }
#=> [{:value=>"one", :label=>"one"}, {:value=>"two", :label=>"two"}]

How to combine 2 strings from an array without repeats in Ruby?

In Ruby, what's an elegant way to combine 2 strings from an array without repeating them?
Example:
array = ['one', 'two', 'three', 'four']
And I want my output to be:
['onetwo', 'onethree', 'onefour', 'twothree', 'twofour', 'threefour']
Seems simple enough but I've been pretty stumped!
Edit: this is for doing something with anagrams so order does not matter. ('onetwo' ends up being equivalent to 'twoone'.)
You can use Arrary#combination, Enumerable#map and Array#join for that.
Code
array.combination(2).map(&:join)
#=> ["onetwo", "onethree", "onefour", "twothree", "twofour", "threefour"]
Explanation
array = ['one', 'two', 'three', 'four']
a = array.combination(2)
#=> #<Enumerator: ["one", "two", "three", "four"]:combination(2)>
To view the contents of the enumerator:
a.to_a
#=> [["one", "two" ], ["one", "three"], ["one" , "four"],
# ["two", "three"], ["two", "four" ], ["three", "four"]]
Then
a.map(&:join)
which has the same effect as:
a.map { |e| e.join }
#=> ["onetwo", "onethree", "onefour", "twothree", "twofour", "threefour"]
If you wanted "twoone" as well as "onetwo", use Array#permutation instead of combination:
array.permutation(2).map(&:join)
#=> ["onetwo" , "onethree", "onefour" , "twoone" , "twothree", "twofour",
# "threeone", "threetwo", "threefour", "fourone", "fourtwo" , "fourthree"]

How can I merge two hashes?

I made two hashes hash1 and hash2 with following keys and values.
Input:
hash1 = {1=>"One", 2=>"Two", 3=>"Three"}
hash2 = {4=>"First", 5=>"Second", 6=>"Third"}
Result:
And I am expecting hash3 to give me a result like
hash3 #=> {1 => "One", 2 => "Two", 3 => "Three", 4 => "First", 5 => "Second", 6 => "Third"}
Can anyone tell me how I can merge these two hashes? Assume that hash3 should contain all keys and all values.
Solution with minimal coding
hash3 = hash1.merge(hash2)
It seems you are looking for Hash#merge
hash1 = {1=>"One", 2=>"Two", 3=>"Three"}
hash2 = {4=>"First", 5=>"Second", 6=>"Third"}
hash3 = hash1.merge hash2
#=> {1 => "One", 2 => "Two", 3 => "Three", 4 => "First", 5 => "Second", 6 => "Third"}
Considering the fact that you access your hash through an increasing sequence of integers, you should think about using an Array instead of a Hash.
result = hash1.values + hash2.values
# => ["One", "Two", "Three", "First", "Second", "Third"]
This way you can still access your values similarly (e.g. result[2] #=> "Three"), but you have a more concise data structure.
If you want 1 to return both "first" and "one", you'll need to store them in an array which will then be the value of which 1 maps to.
results = {}
hash1.each do |key, value|
if results[key].nil?
results[key] = [value]
else
results[key] << value
hash2.each do |key, value|
if results[key].nil?
results[key] = [value]
else
results[key] << value
results[1]
=> ["one", "first"]
Update
You obviously don't want a hash. You want an array with the values only.
results = hash1.values + hash2.values
=> ["one", "two", "three", "first", "second", "third"]
You can access this array just like a hash. Keep in mind that arrays are zero-indexed, so:
results[0]
=> "one"
results[2]
=> "three"
results[5]
=> "third"
Update 2
And now you want a hash after all, because you have unique keys. So:
hash3 = hash1.merge(hash2)
Since you're learning a new language and are still learning how things work. I'd suggest that with whatever you're working with you take a look at the developer docs.
http://ruby-doc.org/
From there you can search for whatever you're looking for and find other interesting things you can do with the Objects ruby provides for you.
To answer your question specifically you'll need merge method for hashes.
{1: 'One', 2: 'Two', 3: 'Three'}.merge(4: 'Four', 5: 'Five', 6: 'Six)
Will yield {1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', 5: 'Five', 6: 'Six'}

Combining two arrays into a hash

I'm trying to combine two arrays into a hash.
#sample_array = ["one", "Two", "Three"]
#timesheet_id_array = ["96", "97", "98"]
I want to output the results into a hash called #hash_array. Is there a simple way to combine the two in a code block so that if you call puts at the end it looks like this in the console
{"one" => "96", "Two" => "97", "Three" => "98"}
I think this could be done in one or two lines of code.
try this
keys = [1, 2, 3]
values = ['a', 'b', 'c']
Hash[keys.zip(values)]
thanks
#hash_array = {}
#sample_array.each_with_index do |value, index|
#hash_array[value] = #timesheet_id_array[index]
end
Imho that looks best:
[:a,:b,:c].zip([1,2,3]).to_h
# {:a=>1, :b=>2, :c=>3}
Dr. Nic suggests 2 options explained well at http://drnicwilliams.com/2006/10/03/zip-vs-transpose/
#hash_array = {}
0.upto(#sample_array.length - 1) do |index|
#hash_array[#sample_array[index]] = #timesheet_id_array[index]
end
puts #hash_array.inspect

Populate ruby Array1 with Array2 String element if and only if Array2 element matches Hash value(not key)

I have a ruby hash:
VALS = { :one => "One", :two => "Two" }
and an Array:
array2 = ["hello", "world", "One"]
Question: How can I populate a new array1 so that it only pulls in any values in array2 that match exactly the values in VALS?
For example, I have tried:
array2.each_with_index do |e,i|
array1 << e if VALS[i] ~= e
end
Along with other thing, and none work. Noob.
Thanks
brilliant! but whent I tried:
p array.select { |i| hash.has_value? i ? array[i+1] : "foo"}
I got an can't convert fixnum error. I must be missing something.
Using nested loops would be very slow if both collections are large. It's better to treat the contents as sets:
array1 = VALS.values & array2
print array1
Output:
One
Here's an option:
hash = { :one => "One", :two => "Two" }
array = ["hello", "world", "One"]
p array.select { |i| hash.has_value? i }
# >> ["One"]
got it!
array.select do |i|
if VALS.has_value? i
result << array[array.index(i)+1]
end
end

Resources