How to map a 2D array to 1D array in PHP - php

I can't figure out how to do the following array_map in php. Any help is much appreciated.
Input:
$arrayA = [
[
'slug' => 'bob',
'name' => 'Bob',
'age' => '10',
],
[
'slug' => 'alice',
'name' => 'Alice',
'age' => '15',
],
[
'slug' => 'carl',
'name' => 'Carl',
'age' => '17',
]
]
Desired Output:
$arrayB = [
'bob' => 'Bob',
'alice' => 'Alice',
'carl' => 'Carl'
]
What I have so far:
Here I am mapping to an array and I know it's not what I want but I can not figure out if there is some syntax for me to return just $x['slug'] => $x['name'] without the brackets?
$arrayB = array_map(fn($x) => [$x['slug'] => $x['name']], $arrayA);
My current output (not what I want):
$arrayB = [
[ 'bob' => 'Bob' ],
[ 'alice' => 'Alice' ],
[ 'carl' => 'Carl' ]
];

There is a PHP function that can do exactly what you want: array_column()
$arrayA = [
[
'slug' => 'bob',
'name' => 'Bob',
'age' => '10',
],
[
'slug' => 'alice',
'name' => 'Alice',
'age' => '15',
],
[
'slug' => 'carl',
'name' => 'Carl',
'age' => '17',
]
];
$arrayB = array_column($arrayA, 'name', 'slug');
That will give you:
Array
(
[bob] => Bob
[alice] => Alice
[carl] => Carl
)
Here's a demo: https://3v4l.org/LGcES

With array_map you cant generate a array with the schema what you want. Use instead array_map foreach. like that:
<?php
$arrayA = [
[
'slug' => 'bob',
'name' => 'Bob',
'age' => '10',
],
[
'slug' => 'alice',
'name' => 'Alice',
'age' => '15',
],
[
'slug' => 'carl',
'name' => 'Carl',
'age' => '17',
]
];
$arrayB = [];
foreach($arrayA as $i) {
$arrayB[$i['slug']] = $i['name'];
}
print_r($arrayB);
// output:
/* Array (
[bob] => Bob
[alice] => Alice
[carl] => Carl
)

Related

Laravel Lumen Collection - Group By With Sum and preserve the values

I'm working on Lumen and my collection has duplicate values, example:
collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 5.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 58.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
])
I would like to sum the value property when the name is the same but preserve other values like (department and phone) and remove duplicates entity, example:
collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 63.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
])
What's the best way to do this?
Try the following:
$newCollection = collect([]);
$collectctions = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 5.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 58.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
]);
foreach ($collectctions as $item) {
if($newCollection->contains('name', $item['name'])){
$index = $newCollection->where('name', $item['name'])->keys()[0];
$newCollection = $newCollection->map(function ($object, $i) use ($index, $item) {
if($i == $index){
$object['value'] += $item['value'];
}
return $object;
});
}
else{
$newCollection->push($item);
}
}
return $newCollection;
This can be achieved using collection functions (https://laravel.com/docs/8.x/collections). In this example I solved it using (groupBy, map, flatten, slice, count and sum).
$data = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
'phone' => '99999-99999',
'value' => 25.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 5.0
],
[
'name' => 'Mary Lisa',
'department' => 'Finance',
'phone' => '88888-88888',
'value' => 58.0
],
[
'name' => 'Lucas Rodrigues',
'department' => 'Marketing',
'phone' => '22222-22222',
'value' => 90.0
]
]);
$data = $data->groupBy('name')->map(function ($item) {
if ($item->count() > 1) {
$item = $item->slice(0, 1)->map(function($subItem) use ($item) {
$subItem['value'] = $item->sum('value');
return $subItem;
});
}
return $item;
})
->flatten(1);
When calling print_r($data->toArray()); we get the following array as result:
Array
(
[0] => Array
(
[name] => John Doe
[department] => Sales
[phone] => 99999-99999
[value] => 25
)
[1] => Array
(
[name] => Mary Lisa
[department] => Finance
[phone] => 88888-88888
[value] => 63
)
[2] => Array
(
[name] => Lucas Rodrigues
[department] => Marketing
[phone] => 22222-22222
[value] => 90
)
)

Restructure multidimensional array based on associative array key

I have the following array:
$products = [
[
'id' => 21,
'name' => 'Floral Dress',
'params' => [
'size' => 14,
'price' => 23.99,
'department' => 'Dresses'
]
],
[
'id' => 413,
'name' => 'Maxi Skirt',
'params' => [
'size' => 10,
'price' => 12.99,
'department' => 'Skirts'
]
],
[
'id' => 78,
'name' => 'A Line Prom Dress',
'params' => [
'size' => 10,
'price' => 79.99,
'department' => 'Dresses'
]
],
[
'id' => 212,
'name' => 'Nude Block High Heels',
'params' => [
'size' => 6,
'price' => 20.99,
'department' => 'Shoes'
]
],
[
'id' => 54,
'name' => 'Denim Trim Dress',
'params' => [
'size' => 8,
'price' => 52.99,
'department' => 'Dresses'
]
],
];
Unfortunately I cannot control how the array is built.
Instead I need to restructure the data so that the array is sorted by the ['params']['department'] key.
So ideally I would take the above and output it like so:
$products = [
'Dresses' => [
[
'id' => 21,
'name' => 'Floral Dress',
'params' => [
'size' => 14,
'price' => 23.99
]
],
[
'id' => 78,
'name' => 'A Line Prom Dress',
'params' => [
'size' => 10,
'price' => 79.99
]
],
[
'id' => 54,
'name' => 'Denim Trim Dress',
'params' => [
'size' => 8,
'price' => 52.99
]
],
],
'Skirts' => [
[
'id' => 413,
'name' => 'Maxi Skirt',
'params' => [
'size' => 10,
'price' => 12.99
]
],
],
'Shoes' => [
[
'id' => 212,
'name' => 'Nude Block High Heels',
'params' => [
'size' => 6,
'price' => 20.99
]
],
]
You could simply iterate over all the products and populate a new associative array holding the departments, which are themselves arrays of corresponding products. See the comments in the code below.
<?php
// same data as in the question, just in one line for better overview
$products = [['id' => 21,'name' => 'Floral Dress','params' => ['size' => 14,'price' => 23.99,'department' => 'Dresses']],['id' => 413,'name' => 'Maxi Skirt','params' => ['size' => 10,'price' => 12.99,'department' => 'Skirts']],['id' => 78,'name' => 'A Line Prom Dress','params' => ['size' => 10,'price' => 79.99,'department' => 'Dresses']],['id' => 212,'name' => 'Nude Block High Heels','params' => ['size' => 6,'price' => 20.99,'department' => 'Shoes']],['id' => 54,'name' => 'Denim Trim Dress','params' => ['size' => 8,'price' => 52.99,'department' => 'Dresses']]];
// initialize empty department array
$departments = array();
// iterate over all the products
foreach ( $products as $product ) {
// get this product's department
$product_department = $product['params']['department'];
// unset the department in the params array
unset( $product['params']['department'] );
// initialize this department as an empty array
// if it doesn't exist yet
if ( !isset( $departments[$product_department] ) ) {
$departments[$product_department] = array();
}
// push this product in its corresponding department
$departments[$product_department][] = $product;
}
var_dump( $departments );
$groupedProducts = [];
foreach ($products as &$product) {
$department = $product['params']['department'];
unset($product['params']['department']);
$groupedProducts[$department] = $product;
}
var_dump($groupedProducts);

matching id's of two array in php

i have 2 array $dizi1 and $dizi2. And these are like this.
$dizi1 = [
[
'id' => 1,
'name' => 'özkan',
'surname' => 'özdemir',
],
[
'id' => 2,
'name' => 'çağrı',
'surname' => 'uğurel',
],
[
'id' => 3,
'name' => 'can',
'surname' => 'tokay'
],
[
'id' => 4,
'name' => 'lütfü',
'surname' => 'uzun'
]
];
$dizi2 = [
[
'id' => 2,
'birthday' => 1993
],
[
'id' => 3,
'birthday' => 1990
],
[
'id' => 4,
'birthday' => 1989
],
[
'id' => 1,
'birthday' => 1987
]
];
and this is what i want
istenenDizi = [
[
'id' => 1,
'name' => 'özkan',
'surname' => 'özdemir',
'birthday' => 1987,
]
];
i reseaxrh a lot bu i cant find a algortihm to do this. I will also create two excel table and i am gonna use this. Can you please help me how can i do this?
Thanksss!
You can use foreach(), array_search(),array_column() like below:-
$istenenDizi = [];
foreach($dizi1 as $dizi1){
$istenenDizi[$dizi1['id']] = $dizi1;
$istenenDizi[$dizi1['id']]['birthday'] = $dizi2[array_search($dizi1['id'],array_column($dizi2,'id'))]['birthday'];
}
$istenenDizi = array_values($istenenDizi);
print_r($istenenDizi);
Output:-https://eval.in/1000838
As you second array unsorted, you can sort it first. Then combine the two array by items. Demo.
usort($dizi2, function($a, $b){ return $a['id'] > $b['id'];});
foreach($dizi1 as $k=>$v){
$v['birthday'] = $dizi2[$k]['birthday'];
$result[] = $v;
}

Sort multi-dimensional array so specific sub-array is first

I want to sort an array so that a specific array with a specific value is shown as the first in the array.
The array I have:
array = [
[0] => [
'id' => 123,
'name' => 'Random'
],
[1] => [
'id' => 156,
'name' => 'keyboard'
],
[2] => [
'id' => 12235,
'name' => 'Text'
],
];
I want the sub-array where the name is 'keyboard' to be the first in line of the big array.
Does anyone have suggestions?
usort Sort an array by values using a user-defined comparison function
$array = [
0 => [
'id' => 123,
'name' => 'Random'
],
1 => [
'id' => 156,
'name' => 'keyboard'
],
2 => [
'id' => 12235,
'name' => 'Text'
],
];
usort($array, function ($item) {
return $item['name'] != 'keyboard';
});
print_r($array);
See the demo
$myArray = [
[0] => [
'id' => 123,
'name' => 'Random'
],
[1] => [
'id' => 156,
'name' => 'keyboard'
],
[2] => [
'id' => 12235,
'name' => 'Text'
],
];
$temp = $myArray[0];
$myArray[0] = $myArray[1];
$myArray[1] = $temp;

Merge arrays inside array dynamically which have the same keys

I am using PHP 5.6. I have an array like this:
$array = [
0 => [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'food' => 'burger',
],
],
1 => [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'drink' => 'coke',
],
],
2 => [
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'food' => 'pizza',
],
],
3 => [
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'drink' => 'pepsi',
],
],
];
Let's say that "food" and "drink" are categories and they can differ depending on how the questionnaire was setup. So there could in fact be "food", "drink", and "dessert" for example. As you can see, there is an array for each person, for each category. What I would like to do is to merge the arrays by each person so that it will instead show up with the following:
$array = [
0 => [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'food' => 'burger',
'drink' => 'coke', // Merged
],
],
1 => [
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'food' => 'pizza',
'drink' => 'pepsi', // Merged
],
],
];
I have looked at array_merge as well as array_merge_recursive, however from everything that I've read, you have to specify the arrays in order to merge them, for example it has to be array_merge(array[0], array[1]). As you can see, I can't exactly do this because there could be 2,3 or even 4 arrays per person which have to be merged together.
So how do I dynamically merge the arrays for each person so that it shows all their information together?
This is not exactly as the result you asked for and it feels pretty messy, but it might be something you can work further with :)
$result = [];
foreach ($array as $answers) {
foreach ($answers as $email => $values) {
if (!isset($result[$email])) {
$result[$email] = $values;
continue;
}
$result[$email] = array_merge($result[$email], $values);
}
}
And the result:
$result === [
'johndrake#gmail.com' => [
'email' => 'johndrake#gmail.com',
'firstname' => 'john',
'lastname' => 'drake',
'food' => 'burger',
'drink' => 'coke',
],
'samwin#gmail.com' => [
'email' => 'samwin#gmail.com',
'firstname' => 'sam',
'lastname' => 'win',
'food' => 'pizza',
'drink' => 'pepsi',
],
]
<?php
$originalArray=array (
0 => array ('johndrake#gmail.com' => array ('email' => 'johndrake#gmail.com', 'firstname' => 'john', 'lastname' => 'drake', 'food' => 'burger')),
1 => array ('johndrake#gmail.com' => array ('email' => 'johndrake#gmail.com', 'firstname' => 'john', 'lastname' => 'drake', 'drink' => 'coke')),
2 => array ('samwin#gmail.com' => array ('email' => 'samwin#gmail.com', 'firstname' => 'sam', 'lastname' => 'win', 'food' => 'pizza')),
3 => array ('samwin#gmail.com' => array ('email' => 'samwin#gmail.com', 'firstname' => 'sam' ,'lastname' => 'win', 'drink' => 'pepsi'))
);
$tempArray=array();
$newArray=array();
foreach($originalArray as $key=>$val){
$valKey=key($val);
if(isset($tempArray[$valKey])){
$newArray[]=array_merge($tempArray[$valKey],$val[$valKey]);
}
else{
$tempArray[$valKey]=$val[$valKey];
}
}
echo "<pre>";print_r($newArray);

Categories