Map Array in child in php - php

I have 2 arrays in php which look like following:
array1 = [product_id = [data], product_id = [data], ..]
[
101 => [
"sku" => "AB01"
],
201 => [
"sky" => "AB02"
],
...
]
array2 = attribute of product with product_id
[
0 => [
"product_id" => 101,
"name" => "pro 1"
],
1 => [
"product_id" => 101,
"size" => "S"
],
2 => [
"product_id" => 201,
"name" => "pro 2"
],
3 => [
"product_id" => 201,
"size" => "S"
],
...
]
What I want is according to product_id in array2 data is pushed in array1 as child array like this
[
101 => [
"sku" => "AB01",
"attributes" => [
0 => [
"product_id" => 101,
"name" => "pro 1"
],
1 => [
"product_id" => 101,
"size" => "S"
]
]
],
201 => [
"sky" => "AB02",
"attributes" => [
0 => [
"product_id" => 201,
"name" => "pro 2"
],
1 => [
"product_id" => 201,
"size" => "S"
]
]
],
...
]
Array length is around 1000 for array1 and >5000 for array2. foreach loop taking too much time. Is there any fast way to achieve it?

About the fastest way I can think of achieving this is using a foreach loop over the second array, as your first array is indexed by the product_id, it is easy to directly insert the new data on each loop...
foreach ( $array2 as $item ) {
$array1[$item['product_id']]['attributes'][] = $item;
}

Maybe it helps you
$array1 = [
101 => [
"sku" => "AB01"
],
201 => [
"sky" => "AB02"
]
];
$array2 = [
0 => [
"product_id" => 101,
"name" => "pro 1"
],
1 => [
"product_id" => 101,
"size" => "S"
],
2 => [
"product_id" => 201,
"name" => "pro 2"
],
3 => [
"product_id" => 201,
"size" => "S"
]
] ;
foreach ($array2 as $result){
if(array_key_exists($result['product_id'], $array1)) {
$array1[$result['product_id']]['attributes'][] = $result;
}
}
print_r($array1);
your result look like this
Array
(
[101] => Array
(
[sku] => AB01
[attributes] => Array
(
[0] => Array
(
[product_id] => 101
[name] => pro 1
)
[1] => Array
(
[product_id] => 101
[size] => S
)
)
)
[201] => Array
(
[sky] => AB02
[attributes] => Array
(
[0] => Array
(
[product_id] => 201
[name] => pro 2
)
[1] => Array
(
[product_id] => 201
[size] => S
)
)
)
)

$arr1=[
101 => [
"sku" => "AB01"
],
201 => [
"sky" => "AB02"
]
];
$arr2=[
0 => [
"product_id" => 101,
"name" => "pro 1"
],
1 => [
"product_id" => 101,
"size" => "S"
],
2 => [
"product_id" => 201,
"name" => "pro 2"
],
3 => [
"product_id" => 201,
"size" => "S"
]
];
foreach ($arr2 as $arr_val ) {
$arr1[$arr_val['product_id']]['attributes'][] = $arr_val;
}
echo "<pre>"; print_r($arr1);

I hope this answer work for you
first array
$arr = [
101 => [
"sku" => "AB01"
],
201 => [
"sky" => "AB02"
],
];
second array
$arr2 = [
0 => [
"product_id" => 101,
"name" => "pro 1"
],
1 => [
"product_id" => 101,
"size" => "S"
],
2 => [
"product_id" => 201,
"name" => "pro 2"
],
3 => [
"product_id" => 201,
"size" => "S"
],
];
finally this what i try to do
$newArr = [];
forEach($arr as $product_id => $product_value){
$attrArr = [];
forEach($arr2 as $key => $value){
if($product_id == $value['product_id']){
$attrArr[] = $value;
$newArr[$product_id] = [
array_keys($product_value)[0] => array_values($product_value)[0],
];
}
}
$newArr[$product_id]['attributes'] = $attrArr;
}
echo '<pre>';
print_r($newArr);
echo '</pre>';

Related

How to remove any sub array and keep only two top levels of a multidimensional array?

I need to modify an array with subarrays and keep only the top two arrays (array -> results - x) and remove any subarray below. For example array "location" & "syncState" should be removed.
Original array:
$device_array = [
"totalCount" => "3",
"results" => [
[
"id" => "2",
"serialNumber" => "DX",
"location" => ["id" => "5", "locationName" => "US"]
],
[
"id" => "4",
"serialNumber" => "DM",
"syncState" => ["id" => "7", "locationName" => "DE"]
],
[
"id" => "5",
"serialNumber" => "C0"
]
]
];
The array should look like this:
Array
(
[totalCount] => 3
[results] => Array
(
[0] => Array
(
[id] => 2
[serialNumber] => DX
)
[1] => Array
(
[id] => 4
[serialNumber] => DM
)
[2] => Array
(
[id] => 5
[serialNumber] => C0
)
)
)
I'm trying to loop through the arrays (sub arrays included) but I can't remove all of the subarrays that sit under $device_array['results'][x].
foreach ($device_array as $key => $value) {
if(is_array($value)) {
unset($device_array['results'][0]['location']);
}
}
You can just loop the results subarray directly and write a custom filter which will modify each entry by reference. Any of the associative elements that hold array type data will be filtered out.
Code: (Demo)
$array = [
"totalCount" => "3",
"results" => [
[
"id" => "2",
"serialNumber" => "DX",
"location" => ["id" => "5", "locationName" => "US"]
],
[
"id" => "4",
"serialNumber" => "DM",
"syncState" => ["id" => "7", "locationName" => "DE"]
],
[
"id" => "5",
"serialNumber" => "C0"
]
]
];
foreach ($array['results'] as &$entry) {
$entry = array_filter($entry, 'is_scalar');
}
var_export($array);
Output:
array (
'totalCount' => '3',
'results' =>
array (
0 =>
array (
'id' => '2',
'serialNumber' => 'DX',
),
1 =>
array (
'id' => '4',
'serialNumber' => 'DM',
),
2 =>
array (
'id' => '5',
'serialNumber' => 'C0',
),
),
)
Or completely functional style: (Demo)
$array['results'] = array_map(
function($entry) {
return array_filter($entry, 'is_scalar');
},
$array['results']
);
var_export($array);
This is how you obtain the output, but I am not so sure if this is what you need in your case
<?php
$array = [
'total' => 2,
'result' => [
[
'id' => 1,
'serialNumber' => 'DX',
'location' => ['id'=>1, 'locationName'=>'US']
],
[
'id' => 2 ,
'serialNumber' => 'DO',
'syncState' => ['id'=>7, 'locationName'=>'DE']
]
]
];
foreach( $array['result'] as $key => $value ){
foreach($value as $key2=>$subarray){
if(is_array($subarray)){
unset($value[$key2]);
}
}
$array['result'][$key] = $value;
}
print_r($array);

Group multi array by key and value PHP

I have an array like the one below
array:4 [▼
0 => array:3 [▼
0 => array:2 [▼
"url" => "https://domain.com.vn"
"value" => "Keyword B3"
]
1 => array:2 [▼
"url" => "https://domain.com.vn"
"value" => "[IMAGES 1]"
]
]
1 => array:3 [▼
0 => array:2 [▼
"url" => "https://domain-4.com.vn"
"value" => "D1"
]
1 => array:2 [▼
"url" => "https://domain-4.com.vn"
"value" => "E3"
]
]
]
I want to combine the above 2 arrays into 1 array as follows (number of items in 2 arrays is always equal):
$result = [
[
"url" => [
"https://domain.com.vn",
"https://domain-4.com.vn"
]
"value" => [
"Keyword B3",
"D1"
]
],
[
"url" => [
"https://domain.com.vn",
"https://domain-4.com.vn"
],
"value" => [
"[IMAGES 1]",
"E3"
]
]
]
I have searched a lot but have not found a solution yet. Thanks for any help.
Because number of items in 2 sub-arrays is always equal, you can use a for loop like this:
$array = [
0 => [
0 => [
'url' => 'https://domain.com.vn',
'value' => 'Keyword B3'
],
1 => [
'url' => 'https://domain.com.vn',
'value' => '[IMAGES 1]'
]
],
1 => [
0 => [
'url' => 'https://domain-4.com.vn',
'value' => 'D1'
],
1 => [
'url' => 'https://domain-4.com.vn',
'value' => 'E3'
]
]
];
$result = [];
for ($i = 0 ; $i < count($array[0]); $i++) {
$result[] = [
'url' => [$array[0][$i]['url'], $array[1][$i]['url']],
'value' => [$array[0][$i]['value'], $array[1][$i]['value']],
];
}
print_r($result);
Result:
Array
(
[0] => Array
(
[url] => Array
(
[0] => https://domain.com.vn
[1] => https://domain-4.com.vn
)
[value] => Array
(
[0] => Keyword B3
[1] => D1
)
)
[1] => Array
(
[url] => Array
(
[0] => https://domain.com.vn
[1] => https://domain-4.com.vn
)
[value] => Array
(
[0] => [IMAGES 1]
[1] => E3
)
)
)
For a dynamic solution, you will need to iterate the first level of the array, then combine the first deep subarray's keys with the return value of array_map()'s special transposing behavior with null and the spread operator.
It sure is a bunch of voodoo, but it is dynamic.
Code: (Demo) (Demo showing different length first level data sets)
var_export(
array_map(
function ($subarray) {
return array_combine(
array_keys($subarray[0]),
array_map(null, ...array_values($subarray))
);
},
$array
)
);
See other other phptranspose tagged Stack Overflow pages to see other usages of the transposing technique.

How to restructure an array so that a sub array key becomes array key

First time posting here and really need some help. Relatively new to php I have an array that I'd like to restructure. I have subjects at top level with students in a sub array. I'd like to restructure so that Students are at the top level with subjects in a sub array.
$startingArray = [
[ "subject" => "Physics",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00005", "Name" => "Jane", "email" => "jane#schooool.com",],
]
],
[ "subject" => "Chemistry",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00005", "Name" => "Jane", "email" => "jane#schooool.com",],
]
],
[ "subject" => "Mathematics",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00006", "Name" => "Fred", "email" => "fred#schooool.com",],
["id" => "00007", "Name" => "Wilma", "email" => "wilma#schooool.com",],
]
],
[ "subject" => "Biology",
"student" => [
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00006", "Name" => "Fred", "email" => "fred#schooool.com",],
["id" => "00008", "Name" => "Alison", "email" => "alison#schooool.com",],
]
]
];
I want my new array to be like this;
$endingArray = [
"students" => [
[ "id" => "00003",
"Name" => "Peter",
"email" => "peter#schooool.com",
"subjects" => [ "Physics", "Chemistry", "Mathematics", ],
],
[ "id" => "00004",
"Name" => "Mary",
"email" => "mary#schooool.com",
"subjects" => [ "Physics", "Chemistry", "Biology", ],
],
[ "id" => "00005",
"Name" => "Jane",
"email" => "jane#schooool.com",
"subjects" => [ "Physics", "Chemistry", ],
],
[ "id" => "00006",
"Name" => "Fred",
"email" => "fred#schooool.com",
"subjects" => [ "Mathematics", "Biology", ],
],
[ "id" => "00007",
"Name" => "Wilma",
"email" => "wilma#schooool.com",
"subjects" => [ "Mathematics", "Biology", ],
],
[ "id" => "00008",
"Name" => "Alison",
"email" => "alison#schooool.com",
"subjects" => [ "Physics", "Biology", ],
],
],
];
I'm trying a 2 stage process. First is to create the new students array without the subjects. This works fine.
Then I'm trying to append the subjects but I know my logic is wrong and the code I have just creates a new row for each student and each subject.
foreach ( $startingArray as $row ) {
$students = $row['student'];
foreach ($students as $student) {
if (!in_array($student, $studentsArray)) {
$studentsArray[] = $student;
}
}
}
the second step just produces garbage
$s1 = $student['id'];
foreach ($startingArray as $row) {
$subject = $row['subject'];
$students = $row['student'];
foreach ($students as $s2) {
if ($s2['id]'] = $s1) {
$student['subjects'] = $subject;
array_push($studentsArray, $student);
}
}
}
}
Any help appreciated!
Here what you can do:
$newArray = [];
foreach ($startingArray as $item) {
foreach ($item['student'] as $student) {
if (empty($newArray[$student['id']])) {
$student['subjects'] = [];
$newArray[$student['id']] = $student;
}
$newArray[$student['id']]['subjects'][] = $item['subject'];
}
}
Sample fiddle here.
Case you need to maintain a sequential id like your example do this
$newArray = [];
foreach ($startingArray as $item) {
foreach ($item["student"] as $student) {
$filter = array_filter($newArray, function ($d) use ($student) {
return ($d["id"] == $student["id"]);
});
if (!$filter) {
$student["subjects"][] = $item['subject'];
$newArray[] = $student;
} else {
$newArray[key($filter)]["subjects"][] = $item["subject"];
}
}
}
$finalArray = [
'students' => $newArray
];
The final result will be
Array
(
[students] => Array
(
[0] => Array
(
[id] => 00003
[Name] => Peter
[email] => peter#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
[2] => Mathematics
)
)
[1] => Array
(
[id] => 00004
[Name] => Mary
[email] => mary#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
[2] => Biology
)
)
[2] => Array
(
[id] => 00005
[Name] => Jane
[email] => jane#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
)
)
[3] => Array
(
[id] => 00006
[Name] => Fred
[email] => fred#schooool.com
[subjects] => Array
(
[0] => Mathematics
[1] => Biology
)
)
[4] => Array
(
[id] => 00007
[Name] => Wilma
[email] => wilma#schooool.com
[subjects] => Array
(
[0] => Mathematics
)
)
[5] => Array
(
[id] => 00008
[Name] => Alison
[email] => alison#schooool.com
[subjects] => Array
(
[0] => Biology
)
)
)
)

how to sort array data in alphabetic key order in php

my collection of data in array which is shown below the index key is A,B,C but i want to store these key in "key" and its key letter's words in "dishes" key
array:3 [
"A" => array:4 [
0 => 37
1 => "Algerian"
2 => 6
3 => "American"
]
"B" => array:6 [
0 => 27
1 => "Belgian"
2 => 20
3 => "Brazilian"
]
and so on..
i wanna sort this array like aplhabetic order as shown below
array:10 [
0 => array:2 [
"key" => "A"
"dishes" => array:2 [
0=>array:2[
"id" => 37
"type" => "Algerian"
],
1=>array:2[
"id" => 6
"type" => "American"
]
]
]
1 => array:2 [
"key" => "B"
"dishes" => array:2 [
0=>array:2[
"id" => 27
"type" => "Belgian"
],
1=>array:2[
"id" => 20
"type" => "Brazilian"
]
]
]
and so on...
This would be a possible solution:
<?php
$input = [
'A' => [
0 => 37,
1 => "Algerian",
2 => 6,
3 => "American"
],
'B' => [
0 => 27,
1 => "Belgian",
2 => 20,
3 => "Brazilian"
]
];
$output = [];
array_walk($input, function($values, $key) use (&$output) {
$entry = [
'key' => $key,
'dishes' => []
];
foreach(array_chunk($values, 2) as $chunk) {
$entry['dishes'][] = [
'id' => $chunk[0],
'type' => $chunk[1]
];
}
$output[] = $entry;
});
print_r($output);
The output of above code obviously is:
Array
(
[0] => Array
(
[key] => A
[dishes] => Array
(
[0] => Array
(
[id] => 37
[type] => Algerian
)
[1] => Array
(
[id] => 6
[type] => American
)
)
)
[1] => Array
(
[key] => B
[dishes] => Array
(
[0] => Array
(
[id] => 27
[type] => Belgian
)
[1] => Array
(
[id] => 20
[type] => Brazilian
)
)
)
)
You have to loop through the original array to create your new structure. Then you can use the ksort function to sort them.
$newArr = new array();
for ($arr as $elem) {
$dishArr = new array();
for($elem['dishes'] as $dish) {
$dishArr[] = $dish['id'];
$dishArr[] = $dish['type'];
}
$newArr[$elem['key']] = $dishArr;
}
ksort($newArr);

group mysql results in multidimensional array

I have the following:
$variants = [
0 => [
"variant_name" => "iPhone 5",
"sku_id" => "2",
"sku" => "GLC-IPH5REDXXXL",
"stock_total" => "10",
"stock_left" => "10",
"retail_price" => 1000,
"on_sale_price" => 0
],
1 => [
"variant_name" => "Red",
"sku_id" => "2",
"sku" => "GLC-IPH5REDXXXL",
"stock_total" => "10",
"stock_left" => "10",
"retail_price" => 1000,
"on_sale_price" => 0
],
2 => [
"variant_name" => "iPhone 6s Plus",
"sku_id" => "4",
"sku" => "GLC-IPH6SP",
"stock_total" => "5",
"stock_left" => "5",
"retail_price" => 1000,
"on_sale_price" => 0
],
3 => [
"variant_name" => "iPhone 6s",
"sku_id" => "13",
"sku" => "GLC-IPH6S",
"stock_total" => "5",
"stock_left" => "5",
"retail_price" => 1000,
"on_sale_price" => 0
]
]
I would like to put them in the following array
0 => [
"sku_id" => "2",
"sku" => "GLC-IPH5REDXXXL",
"stock_total" => "10",
"stock_left" => "10",
"retail_price" => 1000,
"on_sale_price" => 0,
"options" => ['iPhone 4', 'Red'],
"option1" => 'iPhone4',
"option2" => 'Red',
"option3" => null
],
1 => [
"sku_id" => "4",
"sku" => "GLC-IPH6SP",
"stock_total" => "5",
"stock_left" => "5",
"retail_price" => 1000,
"on_sale_price" => 0,
"options" => ['iPhone 6s Plus'],
"option1" => 'iPhone 6s Plus',
"option2" => null,
"option3" => null
],
2 => [
"sku_id" => "13",
"sku" => "GLC-IPH6S",
"stock_total" => "5",
"stock_left" => "5",
"retail_price" => 1000,
"on_sale_price" => 0,
"options" => ['iPhone 6s'],
"option1" => 'iPhone 6s',
"option2" => null,
"option3" => null
]
I can't fill the options with each variant_name
I can't set the option1, option2, option3 with each corresponding variant_name
I've tried a simple foreach($variants as $v) loop on the first array and I got it working until options, option1, option2, option3 from which I get the repeating values.
I just can't figure it out how to do it, any suggestions?
You could use a simple foreach() and perhaps a for(). The for() here is a little inefficient because it runs every time, so it's highly repetitive and continually overwrites...but it works:
foreach($variants as $rows) {
$sku[$rows['sku_id']]['sku_id'] = $rows['sku_id'];
$sku[$rows['sku_id']]['sku'] = $rows['sku'];
$sku[$rows['sku_id']]['stock_total'] = $rows['stock_total'];
$sku[$rows['sku_id']]['stock_left'] = $rows['stock_left'];
$sku[$rows['sku_id']]['retail_price'] = $rows['retail_price'];
$sku[$rows['sku_id']]['on_sale_price'] = $rows['on_sale_price'];
$sku[$rows['sku_id']]['options'][] = $rows['variant_name'];
for($i = 0; $i < 3; $i++)
$sku[$rows['sku_id']]['option'.($i+1)] = (isset($sku[$rows['sku_id']]['options'][$i]))? $sku[$rows['sku_id']]['options'][$i] : NULL;
}
echo print_r(array_values($sku));
Gives you:
Array
(
[0] => Array
(
[sku] => GLC-IPH5REDXXXL
[stock_total] => 10
[stock_left] => 10
[retail_price] => 1000
[on_sale_price] => 0
[options] => Array
(
[0] => iPhone 5
[1] => Red
)
[option1] => iPhone 5
[option2] => Red
[option3] =>
)
[1] => Array
(
[sku] => GLC-IPH6SP
[stock_total] => 5
[stock_left] => 5
[retail_price] => 1000
[on_sale_price] => 0
[options] => Array
(
[0] => iPhone 6s Plus
)
[option1] => iPhone 6s Plus
[option2] =>
[option3] =>
)
[2] => Array
(
[sku] => GLC-IPH6S
[stock_total] => 5
[stock_left] => 5
[retail_price] => 1000
[on_sale_price] => 0
[options] => Array
(
[0] => iPhone 6s
)
[option1] => iPhone 6s
[option2] =>
[option3] =>
)
)
Solution
$result = [];
foreach($variants as $v) {
$result[$v['sku_id']]['sku_id'] = $v['sku_id'];
$result[$v['sku_id']]['sku'] = $v['sku'];
$result[$v['sku_id']]['stock_left'] = $v['stock_left'];
$result[$v['sku_id']]['retail_price'] = price($v['retail_price']);
$result[$v['sku_id']]['options'][] = $v['variant_name'];
if(isset($result[$v['sku_id']]['options'][0])) {
$result[$v['sku_id']]['option1'] = $result[$v['sku_id']]['options'][0];
}
else {
$result[$v['sku_id']]['option1'] = null;
}
if(isset($result[$v['sku_id']]['options'][1])) {
$result[$v['sku_id']]['option2'] = $result[$v['sku_id']]['options'][1];
}
else {
$result[$v['sku_id']]['option2'] = null;
}
if(isset($result[$v['sku_id']]['options'][2])) {
$result[$v['sku_id']]['option3'] = $result[$v['sku_id']]['options'][2];
}
else {
$result[$v['sku_id']]['option3'] = null;
}
}
return $result;

Categories