Hi I have a list of tuples (arrays) and I want to find the tuple that matches an ID in the first object of the tuple. As an example here's what the data looks like
[[object1, stat1],[object2, stat2], etc]
What I want to do is detect an object ID and then grab the stat to go with it. What's the best way to do this?
You could do soemthing like this using ruby select: http://www.ruby-doc.org/core-2.1.1/Enumerable.html#method-i-select
a = [["object1", "stat1"],["object2", "stat2"]]
a.select { |elem| elem.include?("object1") }
I suggest you convert your array
arr = [["object1", "stat1"],["object2", "stat2"],["object3", "stat3"]]
to a hash:
hash = Hash[arr]
#=> {"object1"=>"stat1", "object2"=>"stat2", "object3"=>"stat3"}
or, for Ruby v2.0+
hash = arr.to_h
#=> {"object1"=>"stat1", "object2"=>"stat2", "object3"=>"stat3"}
so that you can retrieve values directly:
hash["object2"] #=> "stat2"
Find you say? Then how about using Enumerable#find?
a = [["object1", "stat1"],["object2", "stat2"],["object3", "stat3"]]
id = a[0][0].object_id
stat = a.find { |e| e[0].object_id == id }[1]
Related
I want to remove a pair of 'duplicates' from an array of strings, where each element has the form R1,R2, with varying numbers. In my case, a duplicate would be R2,R1 because it has the same elements of R1,R2 but inverted.
Given:
a = ['R1,R2', 'R3,R4', 'R2,R1', 'R5,R6']
The resulting array should be like so:
a = ['R1,R2', 'R3,R4', 'R5,R6']
How could I remove the duplicates so I would have the following?
A solution with Set
require 'set'
a.uniq { |item| Set.new(item.split(",")) } # => ["R1,R2", "R3,R4", "R5,R6"]
Here is a working example :
array = ['R1,R2', 'R3,R4', 'R2,R1', 'R5,R6']
array.uniq { |a| a.split(',').sort }
try this,
def unique(array)
pure = Array.new
for i in array
flag = false
for j in pure
flag = true if (j.split(",").sort == i.split(",").sort)
end
pure << i unless flag
end
return pure
end
reference: https://www.rosettacode.org/wiki/Remove_duplicate_elements#Ruby
If the elements of your array are "pairs", they should maybe be actual pairs and not strings, like this:
pairs = [['R1', 'R2'], ['R3', 'R4'], ['R2', 'R1'], ['R5', 'R6']]
And, in fact, since order doesn't seem to matter, it looks like they really should be sets:
require 'set'
sets = [Set['R1', 'R2'], Set['R3', 'R4'], Set['R2', 'R1'], Set['R5', 'R6']]
If that is the case, then Array#uniq will simply work as expected:
sets.uniq
#=> [#<Set: {"R1", "R2"}>, #<Set: {"R3", "R4"}>, #<Set: {"R5", "R6"}>]
So, the best way would be to change the code that produces this value to return an array of two-element sets.
If that is not possible, then you should transform the value at your system boundary when it enters the system, something like this:
sets = a.map {|el| el.split(',') }.map(&Set.method(:new))
I have an array of hashes:
a = [{"ID"=>"FOO", "Type"=>"Name"}, {"ID"=>"1234", "Type"=>"CID"}]
I'm trying to extract the hash where the Type=='CID', then combine the two values to result in CID=1234.
I can do this in multiple steps:
h = a.find{|x| x['Type']=='CID'}
# => {"ID"=>"1234", "Type"=>"CID"}
"#{h['Type']}=#{h['ID']}"
# => "CID=1234"
Is there a way to do this in a one liner?
a.find { |h| h["Type"] == "CID" }&.values_at("Type", "ID")&.join("=")
#=>"CID=1234"
a.find { |h| h["Type"] == "cat" }&.values_at("Type", "ID")&.join("=")
#=> nil
& is Ruby's safe navigation operator, which made it's debut in Ruby v2.3. I added it to cause nil to be returned if there is no match on h["Type"].
You can do it in one line using:
a.select{|x| x['Type']=='CID'}
.map{|x| "type=#{x['Type']},id=#{x['ID']}"}[0]
You may try this:
if we are not having multiple values of Type = "CID":
a.select{|x| x["Type"] == "CID"}.map{|x| x.values_at("Type", "ID")}.join("=")
if we have are having Type="CID"
a.detect{|x| x["Type"]=="CID"}.values_at("Type", "ID").join("=")
If we don't have Type="CID" in above array will throw an error, be cautious.
Need to work in all cases we need to do:
a.detect{|x| x["Type"]=="CID"}.values_at("Type", "ID").join("=") if a.detect{|x| x["Type"]=="CID"}
Example:
my_array = ['2823BII','4A','76B','10J']
[using magical method delete_if_doesnt_contain()]
my_array.map! do |elements|
elements.delete_if_doesnt_contain('A')
end
I want that to set my_array = ['4A']
Even if I could iterate through an array and just return the index of the element that contains an 'A' I'd be happy. Thanks for any help!
Thanks for the answers below, but one more question.
other_array = ['4']
my_var = other_array.to_s
my_array.select!{|x| x.include?(my_var)}
This isn't working for me. What am I missing? Something happen when I converted the array to a string?
Very easy using #select :
my_array = ['2823BII','4A','76B','10J']
my_array.select { |str| str.include?('A') }
# => ["4A"]
Or if you want to modify the source array, do use the bang version of select :-
my_array.select! { |str| str.include?('A') }
Arup's answer is correct.
However, to answer your last question specifically, "iterate through an array and just return the index of the element that contains an 'A'", the "index" method returns the index for a matching element:
my_array.index {|x| x.include?('A') }
The grep method is a lot shorter
my_array = ['2823BII','4A','76B','10J']
my_array.grep /A/
I need to check the contents of a select list drop down which varies depending on a value in another field. I am reading the valid options into an array of strings from a CVS field and comparing by doing the following;
selectContent = []
$browser.select_list(:id,"srch-status-select").options.each {|option| selectContent << option.text}
assert_equal(validContent,selectContent,"Status drop down has wrong values")
Is this correct or is there an existing select_list method which does a similar conversion?
There's no method doing exactly what you want, but a more concise version would be:
selectList = $browser.select_list(:id,"srch-status-select")
selectContent = selectList.options.map(&:text)
Have you tried the .options method? If I'm reading the RDOC for Watir-webdriver correctly, it should return a collection with all the options in the select list.
An alternate way to do this using loops instead of .map is:
elems = Array.new
values = Array.new
elems = #b.select_list(:id => "selectListId").options
0.upto(elems.length - 1) do |i|
values.push elems[i].text
end
then to display the options
0.upto(values.length - 1) do |i|
puts values[i]
end
Forgive me if this has already been asked, I couldn't find it.
I have an array of objects, like:
[<#Folder id:1, name:'Foo', display_order: 1>,
<#Folder id:1, name:'Bar', display_order: 2>,
<#Folder id:1, name:'Baz', display_order: 3>]
I'd like to convert that array into an array just of the names, like:
['Foo','Bar','Baz']
and, while I'm at it it would be nice if I could use the same technique down the road to create an array from two of the parameters, ie name and display order would look like:
[['Foo',1],['Bar',2],['Baz',3]]
What's the best 'Ruby Way' to do this kind of thing?
Thanks!
How about these?
# ['Foo','Bar','Baz']
array = folders.map { |f| f.name }
# This does the same, but only works on Rails or Ruby 1.8.7 and above.
array = folders.map(&:name)
# [['Foo',1],['Bar',2],['Baz',3]]
array = folders.map { |f| [f.name, f.display_order] }
How about:
a.collect {|f| f.name}
You can do
array.map { |a| [a.name, a.display_order] }
To get ['Foo','Bar','Baz'] , you can do: array.map(&:name)
For the second one you could use array.map {|a| [a.id, a.name] }