String substitution for key value pairs in array - arrays

I'm trying to message some data of key values in arrays but stumped.
Here's what's in my array:
data = [ "name=abc", "title=analyst", "group=IT", "id=123"]
The mapping that I'm looking to translate:
mapping = { "name" => "EmployeeName", "title" => "JobTitle", "group" => "BusinessGroup", "id" => "EmployeeID"}
The expected result that I'm after:
data = [ "EmployeeName=abc", "JobTitle=analyst", "BusinessGroup=IT", "EmployeeID=123"]

data.map {|s| s.sub /\w+/, mapping }
# => ["EmployeeName=abc", "JobTitle=analyst", "BusinessGroup=IT", "EmployeeID=123"]

data.map { |str| str.split(/\s*=\s*/).tap { |k,_| k.replace(mapping[k]) }.join('=') }
#=> ["EmployeeName=abc", "JobTitle=analyst", "BusinessGroup=IT", "EmployeeID=123"]
I've split on /\s*=\s*/, rather than "=", in case there are any spaces before or after =.

Given your data array and mapping hash, you can do the following using Array#map:
data.map do |i|
key, value = i.split('=')
"#{mapping[key]}=#{value}"
end
# => ["EmployeeName=abc", "JobTitle=analyst", "BusinessGroup=IT", # "EmployeeID=123"]

> data.map{|a| a.split("=")}.map{|e| mapping.has_key?(e[0]) ? "#{e[0] = mapping[e[0]]}=#{e[1]}" : "#{e[0]}\=#{e[1]}"}
=> ["EmployeeName=abc", "JobTitle=analyst", "BusinessGroup=IT", "EmployeeID=123"]

Related

how to merge values in a list of map in ruby

say I have data structure like List< MAP< String, List>>, I only want to keep the List in map's value,
Like, I want to convert following example:
x = [{"key1" => ["list1", "list1"]}, {"key2" => ["list2", "list2"]},
{"key3" => ["list3", "list3"]}]
to:
y = [["list1", "list1"], ["list2", "list2"], ["list3", "list3"]]
Is there any quick way to do this? Thanks
The quickest thing that comes to mind is to leverage flat_map.
x = [ { "key1" => ["list1", "list1"] },
{ "key2" => ["list2", "list2"] },
{ "key3" => ["list3", "list3"] }]
y = x.flat_map(&:values)
=> [["list1", "list1"], ["list2", "list2"], ["list3", "list3"]]
flat_map is an instance method on Enumerable (https://ruby-doc.org/core-2.6.3/Enumerable.html#method-i-flat_map)
values is an instance method on Hash (https://ruby-doc.org/core-2.6.3/Hash.html#method-i-values)
If you only have 1 key in those hashes then you can do it like this:
y = x.map { |h| h.values[0] }

How to count items in arrays of values in an array of hashes

I have an array of hashes that contain an array of items as the hash value. Here's the structure:
arr = [
{:title => "String1", :link => ["URL1", "URL2"]},
{:title => "String2", :link => ["URL3", "URL4", "URL5"]}
]
I'd like to add a key-value pair that counts the items in each :link like this:
arr = [
{:title => "String1", :link => ["URL1", "URL2"], :link_count => 2},
{:title => "String2", :link => ["URL3", "URL4", "URL5"]}, :link_count => 3
]
I can get to the counts of each :link using this:
arr.map{|x| x[:link].count}
but I can't persist the count as a new key. Any ideas?
You can simply do it by Array#each as below,
> arr.each { |h| h[:link_count] = h[:link].count }
# => [{:title=>"String1", :link=>["URL1", "URL2"], :link_count=>2}, {:title=>"String2", :link=>["URL3", "URL4", "URL5"], :link_count=>3}]
You can use merge! method which alter the original array with the new changes.
arr.map { |x| x.merge!({ link_count: x[:link].count }) }

Looping through an array, displaying elements that match a criteria

I have this big array that I need to break down and only display specific elements within it that match a criteria.
My array looks like this.
[
{
:id => 9789,
:name => "amazing location",
:priority => 1,
:address_id => 12697,
:disabled => false
},
{
:id => 9790,
:name => "better location",
:priority => 1,
:address_id => 12698,
:disabled => false
},
{
:id => 9791,
:name => "ok location",
:priority => 1,
:address_id => 12699,
:disabled => true
}
]
What I need is to only display the elements within this array that have disabled set to true.
However when I try this, I get the error stating no implicit conversion of Symbol into Integer
array.map do |settings, value|
p hash[:disabled][:true]
end
I'm wondering if there is another way, or if there is a way to do this. If anyone could take a look, I would greatly appreciate it.
By providing two arguments to #map on an array, you're actually getting the first hash and then nil. When in reality you just want to loop for each and select those where disabled is true. You can do that instead with Array#select which will filter all elements of the array where the block returns a truthy value:
print array.select { |hash| hash[:disabled] }
=> [{:id=>9791, :name=>"ok location", :priority=>1, :address_id=>12699, :disabled=>true}]
You can try this with a short each or select.
a.each { |k,_v| puts k if k[:disabled] == true }
=> {:id=>9791, :name=>"ok location", :priority=>1, :address_id=>12699, :disabled=>true}
This iterates over each element (hash) inside the array you have and checks if the value of the key disabled on each value is true, and puts the key, just for example, you can set it as you want to do.
Or shorter:
puts a.select { |k,_v| k[:disabled] }
=> {:id=>9791, :name=>"ok location", :priority=>1, :address_id=>12699, :disabled=>true}
Your error shows up when you are treating an array or string as a Hash.
In PHP, array keys can be either numbers or strings, whereas in Ruby associative arrays are a separate data type, called a hash.
Here’s a cheatsheet for various foreach variants, translated into idiomatic Ruby:
Looping over a numeric array (PHP) :
<?php
$items = array( 'orange', 'pear', 'banana' );
# without indexes
foreach ( $items as $item ) {
echo $item;
}
# with indexes
foreach ( $items as $i => $item ) {
echo $i, $item;
}
Looping over an array (Ruby) :
items = ['orange', 'pear', 'banana']
# without indexes
items.each do |item|
puts item
end
# with indexes
items.each_with_index do |item, i|
puts i, item
end
Looping over an associative array (PHP) :
<?php
$continents = array(
'africa' => 'Africa',
'europe' => 'Europe',
'north-america' => 'North America'
);
# without keys
foreach ( $continents as $continent ) {
echo $continent;
}
# with keys
foreach ( $continents as $slug => $title ) {
echo $slug, $title;
}
Looping over a hash (Ruby):
continents = {
'africa' => 'Africa',
'europe' => 'Europe',
'north-america' => 'North America'
}
# without keys
continents.each_value do |continent|
puts continent
end
# with keys
continents.each do |slug, title|
puts slug, title
end
In Ruby 1.9 hashes were improved so that they preserved their internal order. In Ruby 1.8, the order in which you inserted items into a hash would have no correlation to the order in which they were stored, and when you iterated over a hash, the results could appear totally random. Now hashes preserve the order of insertion, which is clearly useful when you are using them for keyword arguments in method definitions. (thanks steenslag for correcting me on this)

Ruby pick up a value in hash of array to reformat into a hash

Is there a way I can pick a value in hash of array, and reformat it to be only hash?
Is there any method I can do with it?
Example
[
{
"qset_id" => 1,
"name" => "New1"
},
{
"qset_id" => 2,
"name" => "New2"
}
]
Result
{
1 => {
"name" => "New1"
},
2 => {
"name" => "New2"
}
}
You can basically do arbitary manipulation using reduce function on array or hashes, for example this will get your result
array.reduce({}) do |result, item|
result[item["qset_id"]] = { "name" => item["name"] }
result
end
You can do the same thing with each.with_object do:
array.each.with_object({}) do |item, result|
result[item["qset_id"]] = { "name" => item["name"] }
end
it's basically the same thing but you don't have to make each iteration return the result (called a 'memo object').
You could iterate over the first hash and map it into a second hash:
h1.map{|h| {h['qset_id'] => {'name' => h['name']}} }
# => [{1=>{"name"=>"New1"}}, {2=>{"name"=>"New2"}}]
... but that would return an array. You could pull the elements into a second hash like this:
h2 = {}
h1.each do |h|
h2[h['qset_id']] = {'name' => h['name']}
end
>> h2
=> {1=>{"name"=>"New1"}, 2=>{"name"=>"New2"}}

Iterate into an array of hash

I'm trying to loop into an array of hash :
response = [
{
"element" => A,
"group" => {"created" => 13, "code" => "Paris.rb", :"rsvp_limit" => 40},
"name" => "CODELAB",
"venue" => {"id" => 17485302, "place" => "la cordée", "visibility" => "public"}
},
{
"element" => B,
"group" => {"created" => 13, "code" => "Paris.rb", :"rsvp_limit" => 40},
"name" => "PARISRB",
"venue" => {"id" => 17485302, "place" => "la cordée", "visibility" => "public"}
}
]
When I run
response[0]["name"], it returns "CODELAB"
response[1]["name"] returns "PARISRB"
How can I make a loop to have the name of each element of this array of hash ?
I tried :
response.each_with_index do |resp, index|
puts array[index]["name"]
end
This is the error I get in my console :
NoMethodError: undefined method `[]' for nil:NilClass
from (pry):58:in `block in __pry__'
The array here seems to be a typo. You meant:
response.each_with_index do |resp, index|
puts resp["name"]
end
The index is not needed because the resp variable is correctly initialized to contain the hash at each iteration.
So it can be simplified to:
response.each do |resp|
puts resp["name"]
end
A little bit shorter:
puts response.map{|hash| hash['name']}
# CODELAB
# PARISRB

Resources