unique multidimensional array based on specific multiple keys - php

I have a multidimensional array which I need to be sorted with unique array based on specific keys. There are same values on item_type_id keys with different partner_id and store_id keys. The result that I expect is when the item_type_id keys have same value and in different partner_id keys with same store_id, it should prefer 10017 value first on partner_id keys.
Example array
[
0 => [
"partner_id" => "10017"
"store_id" => "1000"
"item_type_id" => "2"
"value" => "58"
"category" => "1"
]
1 => [
"partner_id" => "10017"
"store_id" => "1000"
"item_type_id" => "1"
"value" => "63"
"category" => "1"
]
2 => [
"partner_id" => "0"
"store_id" => "1000"
"item_type_id" => "3"
"value" => "29"
"category" => "1"
]
3 => [
"partner_id" => "0"
"store_id" => "1000"
"item_type_id" => "2"
"value" => "58"
"category" => "1"
]
4 => [
"partner_id" => "0"
"store_id" => "1001"
"item_type_id" => "1"
"value" => "65"
"category" => "1"
]
5 => [
"partner_id" => "0"
"store_id" => "1001"
"item_type_id" => "2"
"value" => "58"
"category" => "1"
]
6 => [
"partner_id" => "0"
"store_id" => "1001"
"item_type_id" => "3"
"value" => "29"
"category" => "1"
]
7 => [
"partner_id" => "0"
"store_id" => "1000"
"item_type_id" => "1"
"value" => "65"
"category" => "1"
]
]
Results
[
1000 => [
0 => [
"partner_id" => "10017"
"store_id" => "1000"
"item_type_id" => "2"
"value" => "58"
"category" => "1"
]
1 => [
"partner_id" => "10017"
"store_id" => "1000"
"item_type_id" => "1"
"value" => "63"
"category" => "1"
]
2 => [
"partner_id" => "0"
"store_id" => "1000"
"item_type_id" => "3"
"value" => "29"
"category" => "1"
]
]
1001 => [
0 => [
"partner_id" => "0"
"store_id" => "1001"
"item_type_id" => "1"
"value" => "65"
"category" => "1"
]
1 => [
"partner_id" => "0"
"store_id" => "1001"
"item_type_id" => "2"
"value" => "58"
"category" => "1"
]
2 => [
"partner_id" => "0"
"store_id" => "1001"
"item_type_id" => "3"
"value" => "29"
"category" => "1"
]
]
]
Here is my script
$storeID = [1000,1001];
$createdArray = [];
$previous_item_type_id = "";
$previous_partner_id = "";
foreach($arrays as $array) {
for($i=0; $i<count($storeID); $i++) {
if($array["store_id"] == $storeID[$i]) {
if($array["item_type_id"] != $previous_item_type_id && $array["partner_id"] != $previous_partner_id) {
$createdArray[$storeID[$i]] = [
"partner_id" => $array["partner_id"],
"store_id" => $array["store_id"],
"item_type_id" => $array["item_type_id"],
"value" => $array["value"],
"category" => $array["category"],
];
} else {
$previous_item_type_id = $array["item_type_id"];
$previous_partner_id = $array["partner_id"];
continue;
}
}
}
}
dd($createdArray);

You can use a simple foreach loop to iterate through your array, then use the sub array key store_id to get the key of the final array. push in that final array the value of the current value.
Plus, to remove the duplicated item_type_id, I would write a function that checks if that id already exists in the result.
In example :
$storeID = [1000,1001];
$array = [
0 => [
"partner_id" => "10017",
"store_id" => "1000",
"item_type_id" => "2",
"value" => "58",
"category" => "1"
],
1 => [
"partner_id" => "10017",
"store_id" => "1000",
"item_type_id" => "1",
"value" => "63",
"category" => "1",
],
2 => [
"partner_id" => "0",
"store_id" => "1000",
"item_type_id" => "3",
"value" => "29",
"category" => "1"
],
3 => [
"partner_id" => "0",
"store_id" => "1000",
"item_type_id" => "2",
"value" => "58",
"category" => "1",
],
4 => [
"partner_id" => "0",
"store_id" => "1001",
"item_type_id" => "1",
"value" => "65",
"category" => "1",
],
5 => [
"partner_id" => "0",
"store_id" => "1001",
"item_type_id" => "2",
"value" => "58",
"category" => "1",
],
6 => [
"partner_id" => "0",
"store_id" => "1001",
"item_type_id" => "3",
"value" => "29",
"category" => "1"
],
7 => [
"partner_id" => "0",
"store_id" => "1000",
"item_type_id" => "1",
"value" => "65",
"category" => "1"
]
];
function ItemIdExists($arr, $itemId)
{
foreach ($arr as $subValue)
{
if ($subValue["item_type_id"] == $itemId)
{
return true;
}
}
return false;
}
$result = array();
foreach ($array as $value)
{
$key = $value["store_id"];
if (in_array($key, $storeID))
{
$ItemIdFound = isset($result[$key]) && ItemIdExists($result[$key], $value["item_type_id"]);
if (!$ItemIdFound)
$result[$key][] = $value;
}
}
var_dump($result);
Output
array(2) {
[1000]=>
array(3) {
[0]=>
array(5) {
["partner_id"]=>
string(5) "10017"
["store_id"]=>
string(4) "1000"
["item_type_id"]=>
string(1) "2"
["value"]=>
string(2) "58"
["category"]=>
string(1) "1"
}
[1]=>
array(5) {
["partner_id"]=>
string(5) "10017"
["store_id"]=>
string(4) "1000"
["item_type_id"]=>
string(1) "1"
["value"]=>
string(2) "63"
["category"]=>
string(1) "1"
}
[2]=>
array(5) {
["partner_id"]=>
string(1) "0"
["store_id"]=>
string(4) "1000"
["item_type_id"]=>
string(1) "3"
["value"]=>
string(2) "29"
["category"]=>
string(1) "1"
}
}
[1001]=>
array(3) {
[0]=>
array(5) {
["partner_id"]=>
string(1) "0"
["store_id"]=>
string(4) "1001"
["item_type_id"]=>
string(1) "1"
["value"]=>
string(2) "65"
["category"]=>
string(1) "1"
}
[1]=>
array(5) {
["partner_id"]=>
string(1) "0"
["store_id"]=>
string(4) "1001"
["item_type_id"]=>
string(1) "2"
["value"]=>
string(2) "58"
["category"]=>
string(1) "1"
}
[2]=>
array(5) {
["partner_id"]=>
string(1) "0"
["store_id"]=>
string(4) "1001"
["item_type_id"]=>
string(1) "3"
["value"]=>
string(2) "29"
["category"]=>
string(1) "1"
}
}
}

If I understand the requirements, the desired result will:
group on store_id values and
when item_type_id values collide, the row with a non-zero partner_id value should overwrite a row with a zero partner_id value
Using temporary keys to construct a deeper lookup structure will allow greater efficiency that searching in a loop because key lookups with isset() will always outperform value lookups (with any technique -- even an early return).
After all of the grouping and filtering is done in the loop, flatten the data relating to each store into an associative array of indexed arrays.
Code: (Demo)
$result = [];
foreach ($array as $row) {
if ($row['partner_id'] || !isset($result[$row['store_id']][$row['item_type_id']])) {
$result[$row['store_id']][$row['item_type_id']][$row['partner_id']] = $row;
}
}
var_export(array_map(function($row) { return array_merge(...$row); }, $result));
The snippet above only adds a row into the restructured array if the partner_id is not zero or if the combination of store_id-item_type_id-partner_id has not been encountered before.

Related

How to convert Multidimensional array to Associative array in PhP?

I need to convert the multidimensional array to an associative array.
Please help me to convert the array. Need to remove the keys "sub_code" & "credits" and make the first string as "key" & the second string as "value". I tried a lot of ways but I failed.
Need to convert the below array.
array(9) {
[0]=> array(2)
{
["sub_code"] => string(6) "HS6151"
["credits"] => string(1) "4"
}
[1]=> array(2)
{
["sub_code"] => string(6) "MA6151"
["credits"] => string(1) "4"
}
[2]=> array(2)
{
["sub_code"] => string(6) "PH6151"
["credits"] => string(1) "3"
}
[3]=> array(2)
{
["sub_code"] => string(6) "CY6151"
["credits"] => string(1) "3"
}
[4]=> array(2)
{
["sub_code"] => string(6) "GE6151"
["credits"] => string(1) "3"
}
[5]=> array(2)
{
["sub_code"] => string(6) "GE6152"
["credits"] => string(1) "4"
}
[6]=> array(2)
{
["sub_code"] => string(6) "GE6161"
["credits"] => string(1) "2"
}
[7]=> array(2)
{
["sub_code"] => string(6) "GE6162"
["credits"] => string(1) "2"
}
[8]=> array(2)
{
["sub_code"] => string(6) "GE6163"
["credits"] => string(1) "1"
}
}
Like below.
array(9) {
["HS6151"] => string(1) "4"
["MA6151"] => string(1) "4"
["PH6151"] => string(1) "3"
["CY6151"] => string(1) "3"
["GE6151"] => string(1) "3"
["GE6152"] => string(1) "4"
["GE6161"] => string(1) "2"
["GE6162"] => string(1) "2"
["GE6163"] => string(1) "1"
}
You can use array_column like so:
$array = [
[
'sub_code' => 'HS6151',
'credits' => '4',
],
[
'sub_code' => 'MA6151',
'credits' => '4',
],
];
$result = array_column($array, 'credits', 'sub_code');
print_r($result);
Results in:
Array
(
[HS6151] => 4
[MA6151] => 4
)
Sounds pretty straight forward:
<?php
$input = [
[
"sub_code" => "HS6151",
"credits" => "4"
], [
"sub_code" => "MA6151",
"credits" => "4"
], [
"sub_code" => "PH6151",
"credits" => "3"
], [
"sub_code" => "CY6151",
"credits" => "3"
], [
"sub_code" => "GE6151",
"credits" => "3"
], [
"sub_code" => "GE6152",
"credits" => "4"
], [
"sub_code" => "GE6161",
"credits" => "2"
], [
"sub_code" => "GE6162",
"credits" => "2"
], [
"sub_code" => "GE6163",
"credits" => "1"
]
];
$output = [];
array_walk($input, function($entry) use (&$output) {
$output[$entry["sub_code"]] = $entry["credits"];
});
print_r($output);
The output obviously is:
Array
(
[HS6151] => 4
[MA6151] => 4
[PH6151] => 3
[CY6151] => 3
[GE6151] => 3
[GE6152] => 4
[GE6161] => 2
[GE6162] => 2
[GE6163] => 1
)

Combine arrays with common keys for MYSQL update

I have four $_POST arrays generated from multiple rows of a table
$event_id_array = $_POST['event_id'];
$booth_array = $_POST['booth'];
$parking_array = $_POST['parking'];
$load_in_array = $_POST['load_in'];
I would like to rearrange the arrays to be keyed by $event_id_array as the key of each of the other arrays = an 'event_id'
Arrays are:
$event_id_array =
array(52) {
["'3'"]=>
string(1) "3"
["'5'"]=>
string(1) "5"
["'7'"]=>
string(1) "7"
["'8'"]=>
string(1) "8"
}
$booth_array =
array(52) {
["'3'"]=>
string(1) "1"
["'5'"]=>
string(1) "2"
["'7'"]=>
string(1) "4"
["'8'"]=>
string(0) ""
}
$parking_array =
array(52) {
["'3'"]=>
string(1) "1"
["'5'"]=>
string(1) "2"
["'7'"]=>
string(0) ""
["'8'"]=>
string(0) ""
}
$load_in_array =
array(52) {
["'3'"]=>
string(4) "1:00"
["'5'"]=>
string(4) "2:00"
["'7'"]=>
string(4) "1:15"
["'8'"]=>
string(0) ""
}
I would like the new array to be efficiently update a MySQL database and was thinking a structure of the following would be best:
array(
event_id[3] => array(
'booth' => "1",
'parking' => "1",
'load_in' => "1:00"),
event_id[5] => array(
'booth' => "2",
'parking' => "2",
'load_in' => "2:00"),
event_id[7] => array(
'booth' => "4",
'parking' => "",
'load_in' => "1:15"),
event_id[8] => array(
'booth' => "",
'parking' => "",
'load_in' => ""),
)
or any other way to easily update multiple records easily

Group array items by key value adding an associative element with the grouped values

Having the following array:
$a = [
"category" => "Music",
"items" => [
["ID" => "1", "start_date" => "2018-11-20", "end_date" => "2018-11-28"],
["ID" => "2", "start_date" => "2018-11-22", "end_date" => "2018-11-28"],
["ID" => "3", "start_date" => "2018-11-26", "end_date" => "2018-11-30"],
["ID" => "4", "start_date" => "2018-11-27", "end_date" => "2018-11-31"],
["ID" => "4", "start_date" => "2018-11-29", "end_date" => "2018-11-31"]
]
];
I would like to 'group' the arrays by end_date but not using end_date as key as I saw in other posts or forums, but by adding the value of end_date as a value of a new key.
So that the expected result would be:
array(
"category" => "Music",
"items" => array(
array(
"date" => "2018-11-28",
array("ID" => "1", "start_date" => "2018-11-20", "end_date" => "2018-11-28"),
array("ID" => "2", "start_date" => "2018-11-22", "end_date" => "2018-11-28"),
),
array(
"date" => "2018-11-30",
array("ID" => "3", "start_date" => "2018-11-26", "end_date" => "2018-11-30")
),
array(
"date" => "2018-11-31",
array("ID" => "4", "start_date" => "2018-11-27", "end_date" => "2018-11-31"),
array("ID" => "4", "start_date" => "2018-11-29", "end_date" => "2018-11-31")
)
)
);
Loop the array and build an temporary associative array with the end date as the key.
Then copy the original array and unset the 'items' and add the new temporary array values.
$a = array("category" => "Music",
"items" => array(
array("ID" => "1", "start_date" => "2018-11-20", "end_date" => "2018-11-28"),
array("ID" => "2", "start_date" => "2018-11-22", "end_date" => "2018-11-28"),
array("ID" => "3", "start_date" => "2018-11-26", "end_date" => "2018-11-30"),
array("ID" => "4", "start_date" => "2018-11-27", "end_date" => "2018-11-31"),
array("ID" => "4", "start_date" => "2018-11-29", "end_date" => "2018-11-31")
)
);
foreach($a['items'] as $item){
$new[$item['end_date']]['date'] = $item['end_date'];
$new[$item['end_date']][] = $item;
}
$res = $a;
unset($res['items']);
$res['items'] = array_values($new);
var_dump($res);
Output:
array(2) {
["category"]=>
string(5) "Music"
["items"]=>
array(3) {
[0]=>
array(3) {
["date"]=>
string(10) "2018-11-28"
[0]=>
array(3) {
["ID"]=>
string(1) "1"
["start_date"]=>
string(10) "2018-11-20"
["end_date"]=>
string(10) "2018-11-28"
}
[1]=>
array(3) {
["ID"]=>
string(1) "2"
["start_date"]=>
string(10) "2018-11-22"
["end_date"]=>
string(10) "2018-11-28"
}
}
[1]=>
array(2) {
["date"]=>
string(10) "2018-11-30"
[0]=>
array(3) {
["ID"]=>
string(1) "3"
["start_date"]=>
string(10) "2018-11-26"
["end_date"]=>
string(10) "2018-11-30"
}
}
[2]=>
array(3) {
["date"]=>
string(10) "2018-11-31"
[0]=>
array(3) {
["ID"]=>
string(1) "4"
["start_date"]=>
string(10) "2018-11-27"
["end_date"]=>
string(10) "2018-11-31"
}
[1]=>
array(3) {
["ID"]=>
string(1) "4"
["start_date"]=>
string(10) "2018-11-29"
["end_date"]=>
string(10) "2018-11-31"
}
}
}
}
https://3v4l.org/foKL7
You can use functional-style programming to group and re-index the items subarray without declaring any temporary variables in the global space.
As you iterate each row of $array['items'], use temporary keys for grouping and push rows into their respective group. When finished grouping, re-index the data with array_values().
Code: (Demo)
$array = [
"category" => "Music",
"items" => [
["ID" => "1", "start_date" => "2018-11-20", "end_date" => "2018-11-28"],
["ID" => "2", "start_date" => "2018-11-22", "end_date" => "2018-11-28"],
["ID" => "3", "start_date" => "2018-11-26", "end_date" => "2018-11-30"],
["ID" => "4", "start_date" => "2018-11-27", "end_date" => "2018-11-31"],
["ID" => "4", "start_date" => "2018-11-29", "end_date" => "2018-11-31"]
]
];
$array["items"] = array_values(
array_reduce(
$array["items"],
function ($carry, $row) {
$carry[$row["end_date"]]["data"] = $row["end_date"];
$carry[$row["end_date"]][] = $row;
return $carry;
}
)
);
var_export($array);

PHP foreach loop repeated entries

I need help in order to manipulate a multidimensional array during PHP foreach loop. I have the array below:
$sports = [
[
"id" => "soccer",
"name" => "Football",
"categories" => [
[
"id" => "s1",
"name" => "category 1",
"sportID" => "soccer"
],
[
"id" => "s2",
"name" => "category 2",
"sportID" => "soccer"
],
],
"img" => "/test.png"
],
[
"id" => "tennis",
"name" => "Tennis",
"categories" => [
[
"id" => "t1",
"name" => "category 1",
"sportID" => "tennis"
],
[ "id" => "t2",
"name" => "category 2",
"sportID" => "tennis"
],
],
"img" => "/test.png"
],
];
I have the below foreach in order to take all the sports with the corresponding categories for every sport,
foreach($sports as $s){
$categories = $s['categories'];
foreach($categories as $c){
$cats[] = [
"id" => $c['id'],
"name" => $c['name'],
"sportID" => $s['id'],
];
}
$allCategories[] = $cats;
$data[] = [
"id" => $s['id'],
"name" => $s['name'],
"categories" => $cats,
"img" => $s['img'],
];
$output[] = $data;
}
but the output is not what I expected; instead, I am getting repeated results like the one below:
array(2) {
[0]=>
array(1) {
[0]=>
array(4) {
["id"]=>
string(8) "soccer"
["name"]=>
string(8) "Football"
["categories"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(2) "s1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(8) "soccer"
}
[1]=>
array(3) {
["id"]=>
string(2) "s2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(8) "soccer"
}
}
["img"]=>
string(9) "/test.png"
}
}
[1]=>
array(2) {
[0]=>
array(4) {
["id"]=>
string(8) "soccer"
["name"]=>
string(8) "Football"
["categories"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(2) "s1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(8) "soccer"
}
[1]=>
array(3) {
["id"]=>
string(2) "s2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(8) "soccer"
}
}
["img"]=>
string(9) "/test.png"
}
[1]=>
array(4) {
["id"]=>
string(10) "tennis"
["name"]=>
string(8) "Tennis"
["categories"]=>
array(4) {
[0]=>
array(3) {
["id"]=>
string(2) "s-1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(8) "soccer"
}
[1]=>
array(3) {
["id"]=>
string(2) "s2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(8) "soccer"
}
[2]=>
array(3) {
["id"]=>
string(2) "t1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(10) "tennis"
}
[3]=>
array(3) {
["id"]=>
string(2) "t2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(10) "tennis"
}
}
["img"]=>
string(9) "/test.png"
}
}
}
As you can imagine this is not the correct output, as in the categories of the tennis you can see the categories of the soccer also.
How can I correct my foreach loop in order to get the correct output?
You forget to reset $cats and $data arrays.
<?php
$sports = [
[
"id" => "soccer",
"name" => "Football",
"categories" => [
[
"id" => "s1",
"name" => "category 1",
"sportID" => "soccer"
],
[
"id" => "s2",
"name" => "category 2",
"sportID" => "soccer"
],
],
"img" => "/test.png"
],
[
"id" => "tennis",
"name" => "Tennis",
"categories" => [
[
"id" => "t1",
"name" => "category 1",
"sportID" => "tennis"
],
[ "id" => "t2",
"name" => "category 2",
"sportID" => "tennis"
],
],
"img" => "/test.png"
],
];
foreach($sports as $s){
$categories = $s['categories'];
# before inner loop we need to reset both arrays
$cats = [];
$data = [];
foreach($categories as $c){
$cats[] = [
"id" => $c['id'],
"name" => $c['name'],
"sportID" => $s['id'],
];
}
$allCategories[] = $cats;
$data[] = [
"id" => $s['id'],
"name" => $s['name'],
"categories" => $cats,
"img" => $s['img'],
];
$output[] = $data;
}
echo '<PRE>';
print_r($output);

PHP: manipulate array making value as key recursively

I got this array:
array:2 [▼
0 => array:1 [▼
0 => array:7 [▼
"id" => "1"
"producer" => "Samsung"
"model" => "LE22B541C4W"
"category" => "1"
"production_date" => "2009-05-08"
"status" => "Discontinued"
"type" => "LCD"
]
]
1 => array:1 [▼
0 => array:7 [▼
"id" => "2"
"producer" => "Samsung"
"model" => "P24FHD"
"category" => "1"
"production_date" => "0000-00-00"
"status" => "Discontinued"
"type" => "LCD"
]
]
[...]
]
I would like to take the "ID" value of each array and make as primary key and remove the useless keys like this
array:2 [
1 => array:7 [
"id" => "1"
"producer" => "Samsung"
"model" => "LE22B541C4W"
"category" => "1"
"production_date" => "2009-05-08"
"status" => "Discontinued"
"type" => "LCD"
]
2 => array:7 [
[...]
By now I'm just populate the array using this simple query and a for loop:
foreach ($compatibility as $compElement) {
$sql = "SELECT * FROM product WHERE ID = '$compElement';";
$em = $this->getDoctrine()->getManager();
$stmt = $em->getConnection()->prepare($sql);
$stmt->execute();
$thisElement = $stmt->fetchAll();
$compArray[] = $thisElement;
}
You can do something like this if you don't want to change how you populate your array:
$result = call_user_func_array(
'array_merge_recursive',
$array
);
Output
array(2) {
[0]=>
array(7) {
["id"]=>
string(1) "1"
["producer"]=>
string(7) "Samsung"
["model"]=>
string(11) "LE22B541C4W"
["category"]=>
string(1) "1"
["production_date"]=>
string(10) "2009-05-08"
["status"]=>
string(12) "Discontinued"
["type"]=>
string(3) "LCD"
}
[1]=>
array(7) {
["id"]=>
string(1) "2"
["producer"]=>
string(7) "Samsung"
["model"]=>
string(6) "P24FHD"
["category"]=>
string(1) "1"
["production_date"]=>
string(10) "0000-00-00"
["status"]=>
string(12) "Discontinued"
["type"]=>
string(3) "LCD"
}
}

Categories