How to add subarrays to itself? Ruby [duplicate] - arrays

This question already has answers here:
Ruby: How to concatenate array of arrays into one
(3 answers)
Closed 5 years ago.
I have an array containing of subarrays like this:
arr = [[{"big" => "2055", "small" => -"-10", "thin" => "i"},
{"big" => "2785", "small" => "0", "thin" => "l"}],
[{"big" => "7890", "small" => "3", "thin" => "t"},
{"big" => "2669", "small" => "0,5", "thin" => "f"},
{"big" => "9000", "small" => "2", "fat" => "O"}]]
I want to add subarrays to itself to get an array like this:
arr = [{"big" => "2055", "small" => "-10", "thin" => "i"},
{"big" => "2785", "small" => "0", "thin" => "l"},
{"big" => "7890", "small" => "3", "thin" => "t"},
{"big" => "2669", "small" => "0,5", "thin" => "f"},
{"big" => "9000", "small" => "2", "fat" => "O"}]
Doing like this:
arr.map! {|x| x+x}
I get added subarrays but every hash appears twice. How to do it right?

Do you just want to flatten the array?
arr.flatten
It concatenates every sub-array into one big array, recursively if needed.
[[1,2], [3,4]].flatten
# => [1, 2, 3, 4]
If you want to modify the array in place, you can use :
arr.flatten!
It doesn't matter what the inner-elements look like (integers, strings, hashes), as long as they're not arrays, they won't be touched by flatten.

Ruby have a built in method try use Array.flatten

You can use flatten!:
arr.flatten!
#=> [{"big"=>"2055", "small"=>"-10", "thin"=>"i"},
{"big"=>"2785", "small"=>"0", "thin"=>"l"},
{"big"=>"7890", "small"=>"3", "thin"=>"t"},
{"big"=>"2669", "small"=>"0,5", "thin"=>"f"},
{"big"=>"9000", "small"=>"2", "fat"=>"O"}]

You can try this
arr = arr.flatten

Related

Laravel How to Make Array into a Collection?

Good day everyone, I have this function that can generate time interval and store them to $time.
if(strtotime($startTime) <= strtotime($endTime))
{
$this->time[$i]['room'] = '49';
$this->time[$i]['day'] = 'T-Th';
$this->time[$i]['c_time'] = $start.'-'.$end;
$this->time[$i]['sy'] = '2021-2022';
$this->time[$i]['sem'] = '1st';
}
Sample output of $time is like this
1 => array:5 [▼
"room" => "49"
"day" => "T-Th"
"c_time" => "07:00-08:30"
"sy" => "2021-2022"
"sem" => "1st"
]
2 => array:5 [▼
"room" => "49"
"day" => "T-Th"
"c_time" => "08:30-10:00"
"sy" => "2021-2022"
"sem" => "1st"
]
3 => array:5 [▼
"room" => "49"
"day" => "T-Th"
"c_time" => "10:00-11:30"
"sy" => "2021-2022"
"sem" => "1st"
]]
What should I do so that the output would be a collection->toArray() just like this
array:5 [▼
0 => {#1416 ▼
+"room": "49"
+"day": "M-W"
+"c_time": "13:00-14:00"
+"sy": "2021-2022"
+"sem": "1st"
}
1 => {#1435 ▼
+"room": "49"
+"day": "M-W"
+"c_time": "11:30-13:00"
+"sy": "2021-2022"
+"sem": "1st"
}
2 => {#1433 ▼
+"room": "49"
+"day": "M-W"
+"c_time": "13:00-14:30"
+"sy": "2021-2022"
+"sem": "1st"
}]
Since you did not provide us with where you define the $time variable, I can't help you with any issues there. However, first, instantiate that variable as a collection.
$this->time = collect([]);
And then you can push in the following manner.
$this->time->put($i, (object) [
'room' => '49',
'day' => 'T-Th',
'c_time' => $start.'-'.$end,
'sy' => '2021-2022',
'sem' => '1st',
]);
The simplest way to convert an array to collection is to use Laravel's collect() helper function. It takes an array as a parameter and returns a collection type.
For example if we have this array:
$a = [
['name' => "abc", 'age' =>45],
['name' => "xyz", 'age' =>20],
];
dd(collect($a));
The output will be:

How to merge array from different array

Hi i have problem with merge array,
How to merge array from different array
From Here
Array 1
array:6 [
"patient_name" => "Pasien 4"
"employee_no" => "1114"
"birth_date" => "1990-05-02"
"gender" => "L"
"department_code" => "D0004"
"section_code" => "S0004"
]
Array 2
array:2 [
"kd_layan" => "10000104 "
"nama_layan" => "PAKET MCU ADVANCE (MALE)"
]
To Here
array:8 [
"patient_name" => "Pasien 4"
"employee_no" => "1114"
"birth_date" => "1990-05-02"
"gender" => "L"
"department_code" => "D0004"
"section_code" => "S0004"
"kd_layan" => "10000104 "
"nama_layan" => "PAKET MCU ADVANCE (MALE)"
]
Any solution for this problem?
Thanks
It has very simple solution using array_merge() function of php.
array_merge() function merges one or more arrays into one array.
You can assign one array to the function, or as many as you like.
If two or more array elements have the same key, the last one overrides the others.
in your case use it as below
$arr1=[
"patient_name" => "Pasien 4",
"employee_no" => "1114",
"birth_date" => "1990-05-02",
"gender" => "L",
"department_code" => "D0004",
"section_code" => "S0004"
];
$arr2=[
"kd_layan" => "10000104 ",
"nama_layan" => "PAKET MCU ADVANCE (MALE)"
];
print_r(array_merge($arr1,$arr2));
for more see documentation
use array_merge to merge two array
$array1 = [
"patient_name" => "Pasien 4",
"employee_no" => "1114",
"birth_date" => "1990-05-02",
"gender" => "L",
"department_code" => "D0004",
"section_code" => "S0004",
];
$array2 = [
"kd_layan" => "10000104",
"nama_layan" => "PAKET MCU ADVANCE (MALE)"
];
$res = array_merge($array1, $array2);
echo '<pre>';
print_r($res);
check demo code
Use array_merge()
It merges one or more arrays into one array.
Syntax : array_merge(array1, array2, array3, ...)
use array_merge
$arr1 = [
"patient_name" => "Pasien 4"
"employee_no" => "1114"
"birth_date" => "1990-05-02"
"gender" => "L"
"department_code" => "D0004"
"section_code" => "S0004"
]
arr2 = [
"kd_layan" => "10000104 "
"nama_layan" => "PAKET MCU ADVANCE (MALE)"
]
$result = array_merge($arr1, $arr2);
echo '<pre>';
print_r($result);
Below i have mention an example which will merge two array and the output will be as it is as you want.
$a = array('1' => 'one','2' => 'two');
$b = array('3' => 'three','4' => 'four');
$c = ($a + $b);
print_r($c);

How to create a new hash table if I have one big hash

I have an array of hashes:
{hashed_data = [
{:name => "frontend", :session_total => 145, :byte => 54667},
{:name => "backend_stagging", :session_total => 546, :byte => 895747},
{:name => "backend", :session_total => 5468, :byte => 8957447},
{:name => "frontend", :session_total => 54, :byte => 67387}
]
I must create the following hash. It does not have to be sorted.
hashed_data_modify = {
:frontend => {
:name => "frontend",
:summary => {:session_total => 546, :byte => 54667}
   :backend => {
:name => "backend",
:details => {:session_total => 5468, :byte => 8957447},
   :summary => { :name => "backend_stagging", :session_total => 546, :byte => 895747 }
}
that is, create a new key: frontend where hashed_data[:name] == "frontend" and create a key: backend where hashed_data[:name] == "backend". The frontend key contains only the data for the frontend data and for the backend only the backend.
I tried my sorting_method, it is bad:
hashed_data.select do |h|
if (h[:name] == "frontend") then
return hash = {
:frontend => {
:name => hashed_data[:name],
:details => [:session_total => hashed_data[:stot], :byte_in => hashed_data[:bin]]
}
} # :name => "frontend" etc.
(h[:name == "backend")
return hash = {
:backend => {:name => hashed_data[:name] #:name => "backend"}
} etc.
end
end
Please help.
I'm guessing this is what you want.
hashed_data.group_by { |h| h[:name] }.
map { |_,v| v.max_by { |g| g[:session_total] } }
#=> [{:name=>"frontend", :session_total=>145, :byte=>54667},
# {:name=>"backend_stagging", :session_total=>546, :byte=>895747},
# {:name=>"backend", :session_total=>5468, :byte=>8957447}]
Note that the first calculation is the following.
hashed_data.group_by { |h| h[:name] }
#=> {"frontend"=>[{:name=>"frontend", :session_total=>145, :byte=>54667},
# {:name=>"frontend", :session_total=>54, :byte=>67387}],
# "backend_stagging"=>[{:name=>"backend_stagging", :session_total=>546,
# :byte=>895747}],
# "backend"=>[{:name=>"backend", :session_total=>5468, :byte=>8957447}]}
Firstly, you say you want the first element of the array returned to be:
{:name=>"frontend", :session_total=>546, :byte=>54667}
I'm guessing the value of :session_total is a typo, and should be 145.
Secondly, I assume when two or more hashes have the same value of :name (here just "frontend"), you want to keep the one for which the value session_total is greatest (but that's a truly wild guess).
Thirdly, you seem to want to change the value "backend_staging" to the key :summary. If so, that's not central to the question and just a nuisance for those giving answers, so I've disregarded that requirement.

Add string to array nested inside of hash

I have a set of nested hashes. I would like to add the string "Assembly" to the array value associated with [:dennis_ritche][:languages]
def adding_to_dennis
programmer_hash =
{
:grace_hopper => {
:known_for => "COBOL",
:languages => ["COBOL", "FORTRAN"]
},
:alan_kay => {
:known_for => "Object Orientation",
:languages => ["Smalltalk", "LISP"]
},
:dennis_ritchie => {
:known_for => "Unix",
:languages => ["C"]
}
}
programmer_hash[:dennis_ritchie][:languages] << "Assembly"
end
This is the error I get no implicit conversion of Symbol into Integer"
I think the problem you're seeing is you're manipulating the hash inside the method and as a result are inadvertently returning the wrong thing. This method returns an Array because that's the last operation performed (<< on Array return the modified Array).
To fix it define a method that does the manipulation:
def add_to_hash(hash, programmer = :dennis_ritchie, language = 'Assembly')
hash[programmer][:languages] << language
end
Make that independent of the definition:
programmer_hash =
{
:grace_hopper => {
:known_for => "COBOL",
:languages => ["COBOL", "FORTRAN"]
},
:alan_kay => {
:known_for => "Object Orientation",
:languages => ["Smalltalk", "LISP"]
},
:margaret_hamilton => {
:known_for => "Apollo Program",
:languages => ["Assembly"]
},
:dennis_ritchie => {
:known_for => "Unix",
:languages => ["C"]
}
}
Then call it to manipulate the hash:
add_to_hash(programmer_hash)
The programmer_hash structure is then updated.

Collecting hash entries with identical values

I have an array that looks like below
unorganized_array = [
{:identifier => '1', :groupinfo => [{:color => 'blue', :texture => 'soft'}]},
{:identifier => '1', :groupinfo => [{:color => 'green', :texture => 'hard'}]},
{:identifier => '2', :groupinfo => [{:color => 'red', :texture => 'spiky'}]}]
[{:identifier => '1', :groupinfo => [
{:color => 'blue', :texture => 'soft'}]},
{:identifier => '1', :groupinfo => [
{:color => 'green', :texture => 'hard'}]},
{{:identifier => '2', :groupinfo =>
[{:color => 'red', :texture => 'spiky'}]}
I want to collect all the entries with the same :identifier into that identifier's :groupinfo. This has an extra :identifier => '2' group compared to the previous example:
organized_array = [{:identifier => '1', :groupinfo => [
{:color => 'blue', :texture => 'soft'},
{:color => 'green', :texture => 'hard'}]},
{:identifier => '2', :groupinfo =>
[{:color => 'red', :texture => 'spiky'},
{:color => 'gray', :texture => 'squishy}]}]
I feel like Hash#merge and Hash#inject would be useful here but I'm unsure as to how to implement them.
I'm making unorganized_array from an array that looks like
original_array = [['blue', 'soft', '1', 'irrelevant'], ['green','hard','1','irrelevant1'],
['red','spiky','2','irrelevant2']]
perhaps there is a better method than going from original_array -> unorganized_array -> organized_array?
so far I've been trying to use #map and #each with for loops to group them together, i.e.
unorganized_array = original_array.map! do |first, second, third, fourth|
{:identifier => third, :groupinfo => [{:color => first, :texture => second}]}
end
unorganized_array.map(&:dup)
.group_by { |e| e.delete(:identifier) }
.map { |k, v| [k, v.flat_map { |h| h[:groupinfo] } ] }
.map { |k, v| { identifier: k, groupinfo: v } }
The above gives on the input shown:
#⇒ [ { :groupinfo => [
# { :color => "blue", :texture => "soft" },
# { :color => "green", :texture => "hard" } ],
# :identifier => "1" },
# { :groupinfo => [
# { :color => "red", :texture => "spiky" } ],
# :identifier => "2" } ]
At the moment, you're generating an Array of 2-key Hashes, the second of which contains an Array of attributes. Why not instead use the "identifier" as your key for a Hash? After all, that's precisely what a key is.
This seems cleaner:
{"1"=>[{:color=>"blue", :texture=>"soft"},
{:color=>"green", :texture=>"hard"}],
"2"=>[{:color=>"red", :texture=>"spiky"}]}
And here's one way of generating this:
my_hash = original_array.reduce({}) do |r,s|
r.merge( s[2] => (r[s[2]] || []) + [{color: s[0], texture: s[1]}] )
end
To #the Tin Man's point, understanding Ruby's Enumerable class is a more worthy objective than discovery of any particular solution we can provide.
Working with your Hash
Here's one way of iterating through all your items.
my_hash.each do |key,arr|
puts "Identifier \##{key} has #{arr.size} items"
arr.each_with_index do |item,index|
puts "Item \##{index+1} is #{item[:color]} and #{item[:texture]}"
end
end
Outputs:
Identifier #1 has 2 items
Item #1 is blue and soft
Item #2 is green and hard
Identifier #2 has 1 items
Item #1 is red and spiky
arr =
[{:identifier => '1', :groupinfo => [{:color => 'blue, :texture => 'soft}]},
{:identifier => '1', :groupinfo => [{:color => 'green', :texture => 'hard'}]},
{:identifier => '2', :groupinfo => [{:color => 'red', :texture => 'spiky'}]}]
There are a couple of ways you can do this by building hashes.
Use the form of Hash::new that employs a default that determines h[k] when the hash h does not have a key k.
hash_with_default = Hash.new { |h,k| { identifier: k, groupdata: [] } }
arr.each_with_object(hash_with_default) { |g,h| h[g[:identifier]] =
{ identifier: g[:identifier],
groupdata: h[g[:identifier]][:groupdata] << g[:groupinfo].first } }.values
#=> [{:identifier=>"1", :groupinfo=>[{:color=>"blue", :texture=>"soft"},
# {:color=>"green", :texture=>"hard"}]},
# {:identifier=>"2", :groupinfo=>[{:color=>"red", :texture=>"spiky"}]}]
Use the form of Hash#update (aka merge!) that uses a block to determine the values of keys that are present in both hashes being merged
arr.each_with_object({}) { |g,h| h.update(g[:identifier] => g) { |k,o,n|
{ identifier: o[:identifier], groupinfo: h[k][:groupinfo] + g[:groupinfo] } } }.values
#=> [{:identifier=>"1", :groupinfo=>[{:color=>"blue", :texture=>"soft"},
# {:color=>"green", :texture=>"hard"}]},
# {:identifier=>"2", :groupinfo=>[{:color=>"red", :texture=>"spiky"}]}]
Please consult the doc for the meanings of the three block variables, k, o and n.
I think this is not the best way but I suggested to do:
1- group your array by identifier
unorganized_array.group_by{|x| x[:identifier]}
#=> {"1"=>[{:identifier=>"1", :groupinfo=>[{:color=>"blue", :texture=>"soft"}]},
{:identifier=>"1", :groupinfo=>[{:color=>"green", :texture=>"hard"}]}],
"2"=>[{:identifier=>"2", :groupinfo=>[{:color=>"red", :texture=>"spiky"}]}]}
2 - collect your grouped_array elements in the expected hash and collect the group info values. Now every element into the array contains related items.
group_array.each.collect {|k,g| { :identifier => k, :group_info => g.collect{ |x| x[:groupinfo].last } } }
3- result is the organized array
[{:identifier=>"1", :group_info=>[
{:color=>"blue", :texture=>"soft"},
{:color=>"green", :texture=>"hard"}
]},
{:identifier=>"2", :group_info=>[{:color=>"red", :texture=>"spiky"}]}]

Resources