Restructure array data by chunking, transposing, and merging - php

I have array mentioned below, I will have value always multiple of 3.
$xyz = [
["name" => "abc"],
["name" => "snds"],
["name" => ""),
["number"=> "452"],
["number" => "845120"],
["number" => "84514513200"],
["email" => "ddddf"],
["email" => "dkskns"],
["email" => "kjnksdnkds"]
];
but this is not the proper format for me to perform further operations, so I want this array like mentioned below.
$abc = [
[
"name" => "abc",
"number" => '452',
"email" => "ddddf"
],
[
"name" => "snds",
"number" => "845120",
"email" => "dkskns"
],
[
"name" => "",
"number" => "84514513200",
"email" => "kjnksdnkds"
]
];
note: the array length is dynamic but it will always be multiple of 3

One possibility could be to use the modulo % operator.
In the foreach the value is an array and you could use array_keys to get the key and reset to get the value of the first array element.
$result = [];
$count = 0;
foreach ($xyz as $value) {
if ($count%3 === 0) {
$count = 0;
}
$result[$count][array_keys($value)[0]] = reset($value);
$count++;
}
Demo
That will give you:
array(3) {
[0]=>
array(3) {
["name"]=>
string(3) "abc"
["number"]=>
string(3) "452"
["email"]=>
string(5) "ddddf"
}
[1]=>
array(3) {
["name"]=>
string(4) "snds"
["number"]=>
string(6) "845120"
["email"]=>
string(6) "dkskns"
}
[2]=>
array(3) {
["name"]=>
string(0) ""
["number"]=>
string(11) "84514513200"
["email"]=>
string(10) "kjnksdnkds"
}
}

This will do:
$result = array_map('array_merge', ...array_chunk($xyz, count($xyz) / 3));

Related

PHP check if certain value in different arrays are the same for all

I have couple of arrays like this
$arrayOne = array (
"name" => 'john',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayTwo = array (
"name" => 'smith',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayThree = array (
"name" => 'dave',
"position" => 'instructor',
"hired" => '2009',
"department" => 'math',
);
how can I check if these arrays all have the same hired date?
one way would be compare each individual one:
if($arrayOne['hired'] === $arrayTwo['hired']) & if($arrayOne['hired'] === $arrayThree['hired']) & ...
but is there a cleaner way to do this?
Your initial question and subsequent comment are similar but they are attempting to do different things with the data, with different outcomes. The initial as-asked was:
how can I check if these arrays all have the same hired date
And that can be done with the following:
var_dump(count(array_unique(array_column([$arrayOne, $arrayTwo, $arrayThree], 'hired'))));
// or
$combined = [$arrayOne, $arrayTwo, $arrayThree];
$hiredValues = array_column($combined, 'hired');
$hiredValuesUnique = array_unique($hiredValues);
$length = count($hiredValuesUnique);
var_dump($length);
If the count is 1, they are the same, otherwise they aren't.
But, your follow-up comment was
how can I know which ones are the same
To do that, I'd create a new array that is keyed by that value, and foreach over the source arrays, effectively grouping similar ones for you to further act up.
$final = [];
foreach([$arrayOne, $arrayTwo, $arrayThree] as $array){
if(!array_key_exists($array['hired'], $final)){
$final[$array['hired']] = [];
}
$final[$array['hired']][] = $array;
}
var_dump($final);
Which produces:
array(2) {
[2010]=>
array(2) {
[0]=>
array(4) {
["name"]=>
string(4) "john"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
[1]=>
array(4) {
["name"]=>
string(5) "smith"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
}
[2009]=>
array(1) {
[0]=>
array(4) {
["name"]=>
string(4) "dave"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2009"
["department"]=>
string(4) "math"
}
}
}
I have written the code below:
//Your data
$arrayOne = array (
"name" => 'john',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayTwo = array (
"name" => 'smith',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayThree = array (
"name" => 'dave',
"position" => 'instructor',
"hired" => '2009',
"department" => 'math',
);
function hiredIsTheSameEverywhere(...$arrays) : bool
{
return count(array_count_values(array_column($arrays, "hired"))) === 1;
}
function whereHiredIsTheSame(...$arrays) : array
{
$return = [];
$count = array_count_values(array_column($arrays, "hired"));
foreach($arrays as $array) {
if($count[$array['hired']] > 1) {
$return[$array['hired']][] = $array;
}
}
return $return;
}
//The output
var_dump(hiredIsTheSameEverywhere($arrayOne, $arrayTwo, $arrayThree));
var_dump(whereHiredIsTheSame($arrayOne, $arrayTwo, $arrayThree));
output:
bool(false)
array(1) {
[2010]=>
array(2) {
[0]=>
array(4) {
["name"]=>
string(4) "john"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
[1]=>
array(4) {
["name"]=>
string(5) "smith"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
}
}

Merge two different array data in one array php

I want to merge two different array data in one array, but i'm confuse how to use array_push in this case.
this is example of my data input:
["author"]=>
array(2) {
[0]=>
string(1) "John"
[1]=>
string(1) "Doe"
}
["title"]=>
array(2) {
[0]=>
string(1) "book a"
[1]=>
string(1) "book b"
}
And the result in one array that i mean, like this:
["books"]=>
array(2) {
[0] =>
array(2) {
["author"]=>
string(1) "John"
["title"]=>
string(1) "book a"
}
[1] =>
array(2) {
["author"]=>
string(1) "Doe"
["title"]=>
string(1) "book b"
}
}
I already try using this way but it just return 1 from each array:
$data['books'] = [];
array_push($data['books'], [
'author' => $data['author'],
'title' => $data['title']
]);
if (isset($data['books'])) {
foreach ($data['books'] as $k => $v) {
$data['books'][$k]['author'] = (int)$v['author'];
$data['books'][$k]['title'] = (int)$v['title'];
}
}
result:
["books"]=>
array(1) {
[0]=>
array(2) {
["author"]=>
int(1)
["title"]=>
int(1)
}
}
You have to transpose your arrays with the keys in mind.
function transpose(array $arr){
$transArr = [];
foreach($arr as $keyRow => $subArr) {
foreach($subArr as $keyCol => $value) {
$transArr[$keyCol][$keyRow] = $value;
}
}
return $transArr;
}
This function can be used universally for similar problems. The function comes from this class.
How to use:
$input = [
"author"=> ["John","Doe"],
"title" => ["book a","book b"],
];
$books = transpose($input);
echo '<pre>';
var_export($books);
Or if you want to use the class:
$books = tableArray::create($input)
->transpose()
->fetchAll()
;
Output:
array (
0 =>
array (
'author' => 'John',
'title' => 'book a',
),
1 =>
array (
'author' => 'Doe',
'title' => 'book b',
),
)
If "author" and "title" exist as two arrays, $ input must first be created like this:
$input = ['author' => $arrayAuthor, 'title' => $arrayTitle];

PHP indexed array to nested associative array

I need to convert simple array to nested array according to specific rules. I've achived it but I'm looking for better solution.
SIMPLE:
array(4) {
[0]=>
array(2) {
["id"]=>
string(2) "11"
["type"]=>
int(3)
}
[1]=>
array(2) {
["id"]=>
string(2) "10"
["type"]=>
int(2)
}
[2]=>
array(2) {
["id"]=>
string(1) "1"
["type"]=>
int(1)
}
[3]=>
array(2) {
["id"]=>
string(1) "0"
["type"]=>
int(1)
}
}
EXPECTED EFFECT:
array(1) {
[0]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[1]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[10]=>
array(2) {
["type"]=>
int(2)
["child"]=>
array(1) {
[11]=>
array(2) {
["type"]=>
int(3)
["child"]=>
array(0) {
}
}
}
}
}
}
}
}
}
MY SOLUTION (not very satisfying):
$nestedArray = [];
foreach ($simpleArray as $item)
{
if (!empty($nestedArray))
{
$array = $nestedArray;
reset($array);
$firstKey = key($array);
}
$nestedArray[$item['id']]['child'] = $nestedArray;
$nestedArray[$item['id']]['type'] = $item['type'];
if (!empty($firstKey))
{
unset($nestedArray[$firstKey]);
}
}
As I said, I'm looking for more elegant way to achieve that. Rule are very simply: every next item is child of previous.
You could use recursion:
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
With your example input, it would look like this:
$simpleArray = [
["id" => "11", "type" => 3],
["id" => "10", "type" => 2],
["id" => "1", "type" => 1],
["id" => "0", "type" => 1]
];
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
$nested = nest($simpleArray));
$nested will have the following value:
[
"type" => 1,
"child" => [
"type" => 1,
"child" => [
"type" => 2,
"child" => [
"type" => 3,
"child" => []
]
]
]
]

Remove elements from multidimensional array conditionally

I have this array:
["balance"]=>
array(5) {
[0]=>
array(3) {
["balance"]=>
string(4) "0.00"
["id_item"]=>
string(3) "540"
["item"]=>
string(7) "Lampada"
}
[1]=>
array(3) {
["balance"]=>
string(4) "0.00"
["item"]=>
string(6) "Taglio"
["id_item"]=>
string(3) "541"
}
[2]=>
array(3) {
["balance"]=>
string(4) "0.00"
["item"]=>
string(5) "Piega"
["id_item"]=>
string(3) "542"
}
[3]=>
array(3) {
["balance"]=>
string(4) "2.00"
["item"]=>
string(5) "Piega"
["id_item"]=>
string(3) "542"
}
[4]=>
array(3) {
["balance"]=>
string(4) "7.00"
["item"]=>
string(6) "Gelati"
["id_item"]=>
string(3) "543"
}
As you note, there are 2 arrays with a subkey "id_item" == 542. I need remove only the duplicate with a balance == 0. In detail I need remove the key == 2 (because the balance is 0 and there is another item with same ID with balance > 0)
This is my try but I cannot go further:
if ( is_array ( $array['balance'] ) && count ( $array['balance'] ) > 0 ) {
foreach ( $array['balance'] as $key => $value ) {
if ( isset ( $value['id_item'] ) ) {
$id_item = $value['id_item'];
// re-cycle on the array?
// if next id_item == $id_item && value['balance'] == 0.00 remove
}
}
}
I've tried to make it in few lines, check this out:
$array = [
"balance" => [
[
"balance" => "0.00",
"id_item" => "540",
"item" => "Lampada",
],
[
"balance" => "0.00",
"item" => "Taglio",
"id_item" => "541",
],
[
"balance" => "0.00",
"item" => "Piega",
"id_item" => "542",
],
[
"balance" => "2.00",
"item" => "Piega",
"id_item" => "542",
],
[
"balance" => "7.00",
"item" => "Gelati",
"id_item" => "543",
]
]
];
//get array of id_items
$id_items = array_map(function($e) {
return $e['id_item'];
}, $array['balance']);
//get duplicated keys
$duplicated_keys = array_keys(array_filter(array_count_values($id_items), function($v) {
return $v > 1;
}));
//remove duplicated keys where balance is zero
foreach ($array['balance'] as $k => $balance) {
if(in_array($balance['id_item'], $duplicated_keys) && $balance['balance'] == 0) {
unset($array['balance'][$k]);
}
}

compare array data and get an merged output in php

I have an array like this. I want remove elements with duplicate id and get sum of the count
array(3) {
[0]=>
array(3) {
["Id"]=>
string(1) "1"
["Name"]=>
string(1) "a"
["Count"]=>
string(1) "2"
}
[1]=>
array(3) {
["Id"]=>
string(1) "2"
["Name"]=>
string(1) "b"
["Count"]=>
string(1) "1"
}[2]=>
array(3) {
["Id"]=>
string(1) "1"
["Name"]=>
string(1) "a"
["Count"]=>
string(1) "1"
}
}
and I need to remove elements with duplicate id and get sum of the count as shown below
array(2) {
[0]=>
array(3) {
["Id"]=>
string(1) "1"
["Name"]=>
string(1) "a"
["Count"]=>
string(1) "3"
}[1]=>
array(3) {
["Id"]=>
string(1) "2"
["Name"]=>
string(1) "b"
["Count"]=>
string(1) "1"
}
}
I have gone through many examples.. but couldn't find an answer..
Unfortunately there is no way around looping. Assuming that Name is the same for the same Id or that you don't care about the value of Name:
foreach($array as $value) {
if(!isset($result[$value['Id']])) {
$result[$value['Id']] = $value;
} else {
$result[$value['Id']]['Count'] += $value['Count'];
}
}
// re-index if needed
$result = array_values($result);
Loop the array and build result array using Id as key
If the key Id doesn't exist create it
If it does exist add Count to the current Count
just create a new array, loop through current, create if doesnt exist, and insert values (sum) into new one
what are you doing with duplicates names?
example below. hope it will help.
<?php
$tArr = array(
array(
"Id" => "1",
"Name" => "a",
"Count" => "2",
),
array(
"Id" => "2",
"Name" => "b",
"Count" => "1",
),
array(
"Id" => "1",
"Name" => "a",
"Count" => "1",
)
);
$rez = array();
foreach ($tArr as $key => $element) {
if (empty($rez[$element["Id"]])) {
$rez[$element["Id"]] = $element;
} else {
$rez[$element["Id"]]["Count"] += $element["Count"];
}
}
var_dump($rez);
/** array (size=2)
1 =>
array (size=3)
'Id' => string '1' (length=1)
'Name' => string 'a' (length=1)
'Count' => int 3
2 =>
array (size=3)
'Id' => string '2' (length=1)
'Name' => string 'b' (length=1)
'Count' => string '1' (length=1)**/
Try this
$result = array_diff_assoc($arr, array_unique($arr));
print_r($result);

Categories