Transform multiple values to single key - php

I am using php 7.1 and I have the following array:
<?php
$arr = array (
0 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => 'apples freshness',
),
1 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => 'apples',
),
2 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => 'oranges',
),
3 =>
array (
'Product' => 'Product2',
'Exact_Match_Keyword' => 'apples freshness',
),
4 =>
array (
'Product' => 'Product2',
'Exact_Match_Keyword' => 'apples',
),
);
$arr = array_merge_recursive($arr);
var_dump($arr);
/* WANTED DATA STRUCTURE
$arr = array (
0 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => array('apples freshness', 'apples', 'oranges'),
),
1 =>
array (
'Product' => 'Product2',
'Exact_Match_Keyword' => array('apples freshness', 'apples'),
),
);
*/
I tried to use array_merge_recursive however this does not give me my wanted data structure.
Any suggestions what I am doing wrong?
I appreciate your replies!

You can use array_reduce to handle simple logic like this for you. The example below will provide you with the expected format you've posted.
$example = array_values(
array_reduce(
$arr,
static function ($acc, $row) {
if (!isset($acc[$row['Product']])) {
$acc[$row['Product']] = [
'Product' => $row['Product'],
'Exact_Match_Keyword' => [$row['Exact_Match_Keyword']],
];
} else {
$acc[$row['Product']]['Exact_Match_Keyword'] = array_merge(
$acc[$row['Product']]['Exact_Match_Keyword'],
[$row['Exact_Match_Keyword']]
);
}
return $acc;
}
));
print_r($example);
It can be simplified further if the format you expect is flexible:
$example = array_reduce(
$arr,
static function ($acc, $row) {
if (!isset($acc[$row['Product']])) {
$acc[$row['Product']] = [$row['Exact_Match_Keyword']];
} else {
$acc[$row['Product']] = array_merge(
$acc[$row['Product']],
[$row['Exact_Match_Keyword']]
);
}
return $acc;
}
);
print_r($example);
//Output:
//[
// 'Product1'=> ['apples freshness', 'apples', 'oranges'],
// 'Product2'=> ['apples freshness', 'apples']
//]

I think this gets you what you want. Probably not the most graceful thing in the world but it's roughly the logic you'd want to follow.
$temp = [];
foreach ($arr as $v)
{
$pname = $v['Product'];
if (!isset($temp[$pname]))
{
$temp[$pname] = [];
}
$temp[$pname][] = $v['Exact_Match_Keyword'];
}
$out = [];
foreach ($temp as $k => $v)
{
$out[] = [
'Product' => $k,
'Exact_Match_Name' => $v
];
}
php > var_dump($out);
php shell code:1:
array(2) {
[0] =>
array(2) {
'Product' =>
string(8) "Product1"
'Exact_Match_Name' =>
array(3) {
[0] =>
string(16) "apples freshness"
[1] =>
string(6) "apples"
[2] =>
string(7) "oranges"
}
}
[1] =>
array(2) {
'Product' =>
string(8) "Product2"
'Exact_Match_Name' =>
array(2) {
[0] =>
string(16) "apples freshness"
[1] =>
string(6) "apples"
}
}
}

For future reference, if you would like to use the array_merge_recursive() approach on its own, the input data might have to be a little different from what I can tell.
After looking at the example in the documentation page for array_merge_recursive(), I wonder if the original input data needs to be structured a little differently. I think there needs to be matching inner array keys in order for the final array to have something to combine on for the various inner keys. In the example data below, I used the Products key to combine on for the first inner key.
I don't know if it's possible for your starting data to be structured differently for this process, but if the data could look like the following (based on the example on the documentation page for array_merge_recursive()):
<?php
$ar1 = array(
"Products" => array(
"Product1" => array(
"Exact_Match_Keyword" => array('apples freshness')
)
)
);
$ar2 = array(
"Products" => array(
"Product1" => array(
"Exact_Match_Keyword" => array('apples')
)
)
);
$ar3 = array(
"Products" => array(
"Product1" => array(
"Exact_Match_Keyword" => array('oranges')
)
)
);
$ar4 = array(
"Products" => array(
"Product2" => array(
"Exact_Match_Keyword" => array('apples freshness')
)
)
);
$ar5 = array(
"Products" => array(
"Product2" => array(
"Exact_Match_Keyword" => array('apples')
)
)
);
$result = array_merge_recursive($ar1, $ar2, $ar3, $ar4, $ar5);
print_r($result);
The output should then look like this:
Array
(
[Products] => Array
(
[Product1] => Array
(
[Exact_Match_Keyword] => Array
(
[0] => apples freshness
[1] => apples
[2] => oranges
)
)
[Product2] => Array
(
[Exact_Match_Keyword] => Array
(
[0] => apples freshness
[1] => apples
)
)
)
)

Related

Grouped Array data

I'm trying to figure out how to get data from the following data structure. I managed to group a flat array into the following array, but am finding it difficult to find the proper resources to explain how to get the data out. I'm looking to get the count of the items in each group. Then i'd like to print the ids from the inner array...
array (
'grinds' =>
array (
0 =>
array (
'id' => 16562,
'slug' => 'grinds',
),
1 =>
array (
'id' => 16561,
'slug' => 'grinds',
),
),
'online-grinds' =>
array (
0 =>
array (
'id' => 16566,
'slug' => 'online-grinds',
),
),
)
$my_array1 = array(
'grinds' =>
array(
0 =>
array(
'id' => 16562,
'slug' => 'grinds',
),
1 =>
array(
'id' => 16561,
'slug' => 'grinds',
),
),
'online-grinds' =>
array(
0 =>
array(
'id' => 16566,
'slug' => 'online-grinds',
),
),
);
get counts:
$counts = array();
foreach ($my_array1 as $key => $val) {
$counts[$key] = count($val);
}
var_dump($counts);
yields:
array(2) {
["grinds"]=>
int(2)
["online-grinds"]=>
int(1)
}
get inner ids:
$innerids = array();
foreach ($my_array1 as $key => $val) {
foreach ($val as $key2 => $val2) {
$innerids[] = $val2['id'];
}
}
var_dump($innerids);
yields:
array(3) {
[0]=>
int(16562)
[1]=>
int(16561)
[2]=>
int(16566)
}
You could use array_map and then for every item use array_column and specifing the field name and then use array_count_values to count the unique values.
Then combine those in an array and use the existing key again as the key for then new array.
$arrays = array_map(function($x) {
return [
array_count_values(array_column($x, 'id')),
array_count_values(array_column($x, 'slug'))
];
}, $arrays);
print_r($arrays);
Result
Array
(
[grinds] => Array
(
[0] => Array
(
[16562] => 1
[16561] => 1
)
[1] => Array
(
[grinds] => 2
)
)
[online-grinds] => Array
(
[0] => Array
(
[16566] => 1
)
[1] => Array
(
[online-grinds] => 1
)
)
)
Demo

Looping and combine multiple array to one

I have an array looks like this:
Array
(
[0] => Array
(
[name] => color
[value] => red
)
[1] => Array
(
[name] => shape
[value] => square
)
[2] => Array
(
[name] => price
[value] => $15
)
)
I want to have a result like this:
$myArr = array (
'color' => 'red',
'shape' => 'square',
'price' => '$15'
)
I have tried to loop but can not get it to work.
foreach($myArr as $id => $values){
foreach ($values as $key => $value) {
if($key == 'name') {
//add to array key
} else {
//add to that array key value
}
}
}
hope you guys can help me with solution.
You can use array_column and array_combine
$arr = array(
array("name" => 'color',"value" => 'red'),
array("name" => 'shape',"value" => 'square'),
array("name" => 'price',"value" => '$15')
);
$newArr = array_combine(array_column($arr,'name'),array_column($arr,'value'));
echo "<pre>";
print_r( $newArr );
echo "</pre>";
This will result to:
Array
(
[color] => red
[shape] => square
[price] => $15
)
Doc: array_column, array_combine
$a = [
0 => [
"name" => "color",
"value" => "red",
],
1 => [
"name" => "shape",
"value" => "square",
],
2 => [
"name" => "price",
"value" => "$15",
]
];
$b = [];
foreach($a as $v)
{
$b[$v["name"]] = $v["value"];
}
var_dump($b);
result
array(3) {
["color"]=>
string(3) "red"
["shape"]=>
string(6) "square"
["price"]=>
string(3) "$15"
}
$arr = array
(
0 => array
(
'name' => 'color',
'value' => 'red'
),
1 => array
(
'name' => 'shape',
'value' => 'square'
),
2 => array
(
'name' => 'price',
'value' => '$15'
)
);
$final_array =[];
foreach($arr as $key=> $val){
$final_array[$val['name']] = $val['value'];
}
echo "<pre>"; print_r($final_array);

How to merge these 2 arrays in PHP?

I have an array $array1 with different amount of key and value pairs:
Array
(
[0] => Array
(
[ID] => 39
[title] => Apple
)
[1] => Array
(
[ID] => 40
[title] => Orange
)
)
and another array $array2:
Array
(
[0] => 273
[1] => 386
)
And I want to get this:
Array
(
[0] => Array
(
[ID] => 39
[title] => Apple
[pages] => 273
)
[1] => Array
(
[ID] => 40
[title] => Orange
[pages] => 386
)
)
The number of items in each array is the same and the correspond, so, we don't need to check this, so, how to merge it like that?
use array_replace_recursive if you want merge with integer keys, or array_merge_recursive if you want merge only string keys
<?php
$a1 = array(
0 => array
(
"ID" => 39,
"title" => "Apple"
),
1 => array(
"ID" => 40,
"title" => "Orange"
)
);
$a2 = array(
0 => array
(
"pages" => 273,
"year" => 1981
),
1 => array(
"pages" => 386,
"year" => 1979
)
);
$a3 = array_replace_recursive($a1, $a2);
var_dump($a3);
Result:
array(2) {
[0] =>
array(4) {
'ID' =>
int(39)
'title' =>
string(5) "Apple"
'pages' =>
int(273)
'year' =>
int(1981)
}
[1] =>
array(4) {
'ID' =>
int(40)
'title' =>
string(6) "Orange"
'pages' =>
int(386)
'year' =>
int(1979)
}
}
Answer for updated question:
<?php
$a1 = array(
0 => array
(
"ID" => 39,
"title" => "Apple"
),
1 => array(
"ID" => 40,
"title" => "Orange"
)
);
$a2 = array(
0 => 31,
1 => 324
);
$defaultValue = 0;
foreach ($a1 as $key => $value) {
$a1[$key]['pages'] = isset($a2[$key]) ? $a2[$key] : $defaultValue;
}
var_dump($a1);
Result:
array(2) {
[0] =>
array(3) {
'ID' =>
int(39)
'title' =>
string(5) "Apple"
'pages' =>
int(31)
}
[1] =>
array(3) {
'ID' =>
int(40)
'title' =>
string(6) "Orange"
'pages' =>
int(324)
}
}
Try this code :-
$newArray = array();
$i=0;
foreach($array1 as $value){
$newArray[$i] = $value;
$newArray[$i][] = $array2[$i];
$i++;
}
Here is code that produce exactly output you are looking for :
<?php
$list1 = array(array('id' => 39,'title' => 'Apple'),array('id' => 40,'title' => 'Orange'));
$list2 = array(array('pages' => 273,'year' => 1981),array('pages' => 386,'year' => 1979));
$newList = array();
$i=0;
foreach($list1 as $firstList){
foreach($list2 as $secondList){
$newList[$i] = array_merge($firstList, $secondList);
}
$i++;
}
echo"<pre>"; print_r($newList); echo"</pre>";
?>
OUTPUT :
Try this
array1[0][pages]=array2[0][pages];
array1[0][year]=array2[0][year];
array1[1][pages]=array2[1][pages];
array1[1][year]=array2[1][year];
for($i=0; $i<count($array1); ++$i){
$array1[$i]['pages'] = $array2[$i];
}
var_dump($array1);
$output = array();
array_walk( $array1, function( $v, $k ) use ( $array2, &$output ) {
$output[] = array_merge( $v, $array2[$k] );
});
If the sizes of the 2 arrays are same you could do something like this
$arr1 = array(
array(
'ID' => 39,
'title' => 'Apple'
),
array(
'ID' => 40,
'title' => 'Orange'
)
);
$arr2 = array(
273,
386
);
$merged = array();
for ($i = 0; $i < count($arr1); $i++) {
$merged[] = array_merge($arr1[$i], array('pages' => $arr2[$i]));
}
var_dump($merged);
or if you don't want a new array
for ($i = 0; $i < count($arr1); $i++) {
$arr1[$i]['pages'] = $arr2[$i];
}

Strip layer from mulitdimensional array PHP

I am having some difficulty manipulating the below array. I have tried various things and I feel like there should be a simple way to achieve this, but I cannot seem to figure it out. Any tips or help greatly appreciated, thanks!
Array
(
[0] => Array
(
[0] => Array
(
[Color] => Blue
)
[1] => Array
(
[Size] => S
)
)
[1] => Array
(
[0] => Array
(
[Color] => Blue
)
[1] => Array
(
[Size] => M
)
)
)
My desired outcome is:
Array
(
[0] => Array
(
[Color] => Blue
[Size] => S
)
[1] => Array
(
[Color] => Blue
[Size] => M
)
)
This works:
$items = array(
array(
array("Color" => "Blue"),
array("Size" => "S")
),
array(
array("Color" => "Blue"),
array("Size" => "M")
)
);
$new_items = array();
foreach ($items as $item) {
$collect = array();
foreach ($item as $values) {
foreach ($values as $key => $value) {
$collect[$key] = $value;
}
}
$new_items[] = $collect;
}
var_dump($new_items);
Your array is 3 deep, so you need at least 3 nested loops.
Output:
array(2) {
[0]=>
array(2) {
["Color"]=>
string(4) "Blue"
["Size"]=>
string(1) "S"
}
[1]=>
array(2) {
["Color"]=>
string(4) "Blue"
["Size"]=>
string(1) "M"
}
}
2 loops are enough with array_merge
$a = array(
array(
array(
'Color' => 'Blue'
),
array(
'Size' => 'S'
),
),
array(
array(
'Color' => 'Blue'
),
array(
'Size' => 'M'
),
),
);
$c = array();
foreach($a as $b)
{
$ca = array();
if(is_array($b))
{
foreach($b as $array)
{
$ca = array_merge($ca, $array);
}
$c[] = $ca;
}
}
echo '<pre>'.print_r($c,true);
You can use array_map for this:
<?php
function combine($elementArray)
{
return array($elementArray[0]["Color"], $elementArray[1]['Size']);
}
$originalArray = array(
0 => array(
0 => array("Color" => "Blue"),
1 => array("Size" => "S")
),
1 => array(
0 => array( "Color" => "Blue"),
1 => array("Size" => "M")
)
);
$combinedArray = array_map("combine", $originalArray);
echo "<pre>";
print_r($combinedArray);
?>
Also you can use anonymous functions and do it like a pro ;)
$combinedArray = array_map(
function($element){
return array(
"Color" => $element[0]["Color"],
"Size" => $element[1]['Size']
);
},$originalArray);
Or you can even use array_reduce example:
$reducedArray = array_reduce($originalArray, function($result, $item){
$result[] = array(
'Color' => $item[0]['Color'],
'Size' => $item[1]['Size']
);
return $result;
});
Hope this will help
$array =
array(
array(
array(
'color'=>'Blue'
),
array(
'size'=>'s'
)
),
array(
array(
'color'=>'Red'
),
array(
'size'=>'m'
)
)
);
$mA = array();
foreach($array as $k=>$a){
array_push($mA,array_merge($a[0],$a[1]));
}
var_dump($mA);

PHP multi-dimentional array condensing

I am using an array like this for a static file cache:
[
key => data => [
key1 => data => [...]
=> expires => 123456
key2 => data => [...]
=> expires => 123456
]
=> expires => 123456
]
This can be many levels deep (sometimes 10-15 levels).
What I would like to do is return only the values of data, so for instance, to create an array like so
[
key => key1 => [...]
=> key2 => [...]
]
how would I do this?
EDIT
print_r of the structure
Array (
[key] =>
Array (
[data] =>
Array (
[key1] =>
Array (
[data] => Array ( ... )
[expires] => 12345678)
[key2] =>
Array (
[data] => Array ( ... )
[expires] => 12345678
)
)
[expires] => 12345678
)
)
You can use recursive function like this:
function extractValues($array, &$result){
foreach($array as $key1 => $val1){
if($key1 == 'data' && is_array($val1)) {
foreach($val1 as $key2 => $val2){
if(is_array($val2)) {
$result[$key2] = array();
extractValues($val2, $result[$key2]);
} else {
$result[$key2] = $val2;
}
}
} else if(!in_array($key1, array('expires'))) {
$result[$key1] = array();
extractValues($val1, $result[$key1]);
}
}
return $result;
}
It will work on array structure like this:
$test = array(
'key' => array(
'data' => array(
'key1' => array(
'data' => array(
'key11' => 11,
'key12' => 12,
),
),
'key2' => array(
'data' => array(
'key21' => 21,
'key22' => 22,
),
),
),
'expires' => 12345,
),
);
$result = array();
extractValues($test, $result);
var_dump($result);
This is the result of the var_dump() hope meets your requirement:
array(1) {
["key"]=>
array(2) {
["key1"]=>
array(2) {
["key11"]=>
int(11)
["key12"]=>
int(12)
}
["key2"]=>
array(2) {
["key21"]=>
int(21)
["key22"]=>
int(22)
}
}
}

Categories