So, I am sending data from View to Controller and need to save all (multiple) data in DB.
in view I am using category[], status_number[] and name[] to collect data, then I got this:
[
'category' => [
(int) 0 => 'c',
(int) 1 => 'c1',
(int) 2 => 'c2'
],
'status_number' => [
(int) 0 => 'sn',
(int) 1 => 'sn1',
(int) 2 => 'sn2'
],
'name' => [
(int) 0 => 'n',
(int) 1 => 'n1',
(int) 2 => 'n2'
]
]
now I need to transform (combine) this array so that I can store it to DB in this structure
[
'(int) 0' => [
category => 'c',
status_number => 'sn',
name => 'n'
],
'(int) 1' => [
category => 'c1',
status_number => 'sn1',
name => 'n1'
],
'(int) 2' => [
category => 'c2',
status_number => 'sn2',
name => 'n2'
]
]
You can try something like that:
<?php
$array = [
'category' => [
'c',
'c1',
'c2'
],
'status_number' => [
'sn',
'sn1',
'sn2'
],
'name' => [
'n',
'n1',
'n2'
]
];
$result = [];
array_walk($array, function($data, $key) use (&$result){
foreach($data as $numericKey => $value) {
$result[$numericKey][$key] = $value;
}
});
print_r($result);
As the result it gives:
Array
(
[0] => Array
(
[category] => c
[status_number] => sn
[name] => n
)
[1] => Array
(
[category] => c1
[status_number] => sn1
[name] => n1
)
[2] => Array
(
[category] => c2
[status_number] => sn2
[name] => n2
)
)
Related
This question already has answers here:
Sort multidimensional array based on another array [duplicate]
(3 answers)
Closed 26 days ago.
Hi I have an array that looks like this
array[
0 => array[
'id' => 1,
'name' => 'Test 1'
'classId' => 3
],
1 => array[
'id' => 1,
'name' => 'Test 1'
'classId' => 15
],
2 => array[
'id' => 1,
'name' => 'Test 1'
'classId' => 17
],
]
And I have another array that contains classIds like:
classIds = [15, 17, 3]
And I want to sort my array based on classIds
I can do a a double loop to compare it. I am just wondering is there anyother way to get it done?
Actually one loop i enough:
<?php
$order = [15, 17, 3];
$input = [
[
'id' => 1,
'name' => 'Test 1',
'classId' => 3,
],
[
'id' => 1,
'name' => 'Test 1',
'classId' => 15,
],
[
'id' => 1,
'name' => 'Test 1',
'classId' => 17,
],
];
$output = [];
array_walk($input, function($entry) use ($order, &$output) {
$output[array_search($entry['classId'], $order)] = $entry;
});
ksort($output);
print_r($output);
In case you consider array_search(...) also a "loop" (though it internally works different), that would be an alternative which produces the same output:
<?php
$order = array_flip([15, 17, 3]);
$input = array_values([
[
'id' => 1,
'name' => 'Test 1',
'classId' => 3,
],
[
'id' => 1,
'name' => 'Test 1',
'classId' => 15,
],
[
'id' => 1,
'name' => 'Test 1',
'classId' => 17,
],
]);
$output = [];
array_walk($input, function($entry, $index) use ($order, &$output) {
$output[$order[$entry['classId']]] = $entry;
});
ksort($output);
print_r($output);
The output of both approaches is:
Array
(
[0] => Array
(
[id] => 1
[name] => Test 1
[classId] => 15
)
[1] => Array
(
[id] => 1
[name] => Test 1
[classId] => 17
)
[2] => Array
(
[id] => 1
[name] => Test 1
[classId] => 3
)
)
You can sort the array directly and in-place using usort and an anonymous comparison function that retrieves the target indices from $classIds.
Given
<?php
$arr = array(
0 => array(
'id' => 1,
'name' => 'Test 1',
'classId' => 3
),
1 => array(
'id' => 1,
'name' => 'Test 1',
'classId' => 15
),
2 => array(
'id' => 1,
'name' => 'Test 1',
'classId' => 17
),
);
$classIds = [15, 17, 3];
you can sort $arr with
// Create assoc array mapping classIds to their desired sorted position.
$classIdsOrder = array_combine($classIds, range(0, count($classIds)-1));
// Sort $arr according to the 'classId' order described by $classIdsOrder
usort($arr, function ($left, $right) use ($classIdsOrder) {
return $classIdsOrder[$left['classId']] <=> $classIdsOrder[$right['classId']];
});
print_r($arr);
which outputs
Array
(
[0] => Array
(
[id] => 1
[name] => Test 1
[classId] => 15
)
[1] => Array
(
[id] => 1
[name] => Test 1
[classId] => 17
)
[2] => Array
(
[id] => 1
[name] => Test 1
[classId] => 3
)
)
Try it online!
If someone has already done it, the idea is to merge different arrays into one and also merge the values sum of price, qty only for the identical keys.
In my example I only put two arrays to be merged $arr1, $arr2 but the idea is to do it dynamically because I do not have a defined number of arrays , I can have 2 as I can have 15.
Example:
<?php
$arr1 = [
51 => [
'name' => 'p1',
'price' => '20',
'qty' => '10',
'category' => 'c1'
],
3 => [
'name' => 'p2',
'price' => '10.50',
'qty' => '3',
'category' => 'c2'
]
];
$arr2 = [
3 => [
'name' => 'p3',
'price' => '23',
'qty' => '22',
'category' => 'c1'
],
102 => [
'name' => 'p4',
'price' => '10.50',
'qty' => '8',
'category' => 'c2'
]
];
Code :
mergeArrays(($arr1 + $arr2));
function mergeArrays($array)
{
$mergedArray = [];
foreach ($array as $k => $arr) {
foreach ($arr as $key => $value) {
if (!isset($mergedArray[$key])) {
$mergedArray[$k][$key] = $value;
} else {
$mergedArray[$key] += $value;
}
}
}
print_r($mergedArray);
//return $mergedArray;
}
Result:
Array
(
[51] => Array
(
[name] => p1
[price] => 20
[qty] => 10
[category] => c1
)
[3] => Array
(
[name] => p2
[price] => 10.50
[qty] => 3
[category] => c2
)
[102] => Array
(
[name] => p4
[price] => 10.50
[qty] => 8
[category] => c2
)
)
Expected result:
Array
(
[51] => Array
(
[name] => p1
[price] => 20
[qty] => 10
[category] => c1
)
[3] => Array
(
[name] => p3 // the last erray value
[price] => 33.50 //sum
[qty] => 25 //sum
[category] => c1 // the last erray value
)
[102] => Array
(
[name] => p4
[price] => 10.50
[qty] => 8
[category] => c2
)
)
Using the ...$in to indicate any number of arrays can be passed to the function and then a couple of loops will do the job for you
$arr1 = [ 51 => [ 'name' => 'p1', 'price' => '20', 'qty' => '10', 'category' => 'c1' ],
3 => [ 'name' => 'p2', 'price' => '10.50', 'qty' => '3', 'category' => 'c2' ]
];
$arr2 = [ 3 => [ 'name' => 'p3', 'price' => '23', 'qty' => '22', 'category' => 'c1' ],
102 => [ 'name' => 'p4', 'price' => '10.50', 'qty' => '8', 'category' => 'c2' ]
];
function myMerge(Array ...$in)
{
$new = $in[0];
for($i=1; $i<count($in); $i++){
foreach($in[$i] as $idx => &$a) {
if( isset($new[$idx]) ){
$new[$idx]['qty'] += $a['qty'];
$new[$idx]['price'] += $a['price'];
} else {
$new[$idx] = $a;
}
}
}
return $new;
}
print_r( myMerge($arr1, $arr2) );
RESULT
Array
(
[51] => Array
(
[name] => p1
[price] => 20
[qty] => 10
[category] => c1
)
[3] => Array
(
[name] => p2
[price] => 33.5
[qty] => 25
[category] => c2
)
[102] => Array
(
[name] => p4
[price] => 10.50
[qty] => 8
[category] => c2
)
)
hope this helps
<?php
$arr1 = [
51 => [
'name' => 'p1',
'price' => '20',
'qty' => '10',
'category' => 'c1'
],
3 => [
'name' => 'p2',
'price' => '10.50',
'qty' => '3',
'category' => 'c2'
]
];
$arr2 = [
3 => [
'name' => 'p3',
'price' => '23',
'qty' => '22',
'category' => 'c1'
],
102 => [
'name' => 'p4',
'price' => '10.50',
'qty' => '8',
'category' => 'c2'
]
];
$result = [];
foreach([$arr1, $arr2] as $arr) {
$keysFromCurrentArray = array_keys($arr);
foreach ($keysFromCurrentArray as $key) {
if(array_key_exists($key, $result)) {
$result[$key] = [
$result[$key]['name'] = $arr[$key]['name'],
$result[$key]['price'] += $arr[$key]['price'],
$result[$key]['qty'] += $arr[$key]['qty'],
$result[$key]['category'] = $arr[$key]['category'],
];
} else {
$result[$key] = $arr[$key];
}
}
}
var_export($result);
output :
array (
51 =>
array (
'name' => 'p1',
'price' => '20',
'qty' => '10',
'category' => 'c1',
),
3 =>
array (
0 => 'p3',
1 => 33.5,
2 => 25,
3 => 'c1',
),
102 =>
array (
'name' => 'p4',
'price' => '10.50',
'qty' => '8',
'category' => 'c2',
),
)
Using array merge in loop is NOT optimal
You can put arrays in one like this:
$arrays = [ [1, 2], [2, 3], [5,8] ];
And then:
$merged = array_merge([], ...$arrays);
The Array:
$array = [
'A',
'B',
'C'
//and so on
]
Expected result:
$array = [
[
'value' => 'A',
'names' => [
'1' => 'A',
'2' => 'A'
],
'child' => [
'value' => 'B',
'names' => [
'1' => 'B',
'2' => 'B'
],
'child' => [
'value' => 'C',
'names' => [
'1' => 'C',
'2' => 'C'
],
'child' => [
// and so on...
]
]
]
]
];
I've researched a function array_merge_recursive.
But this function doesn't shift array.
Need to achieve: staggered array from simple array.
I've not understood what you want inside names, however this code is generating the array you want:
$array = [
'A',
'B',
'C'
//and so on
];
$result = [];
for($i = count($array) - 1 ; $i >= 0 ; $i--){
$result = [
'value' => $array[$i],
'names' => [
'1' => $array[$i],
'2' => $array[$i],
],
'child' => $result
];
}
Output:
Array
(
[value] => A
[names] => Array
(
[1] => A
[2] => A
)
[child] => Array
(
[value] => B
[names] => Array
(
[1] => B
[2] => B
)
[child] => Array
(
[value] => C
[names] => Array
(
[1] => C
[2] => C
)
[child] => Array
(
)
)
)
)
I have an associative array key/values indicating a group. I'd like to shuffle the array so that the groups are in a random order but so that the items in the groups are shuffled only within their group. In other words, I want to take something like this:
[
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Spike",
"group" => 3
]
]
And return something a bit more like this:
[
[
"name" => "Spike",
"group" => 3
]
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
]
I realise this is probably possible with two or three sorts, but it would be great if this could be done with a single usort.
Basically, my solution shuffles the input array, temporarily restructures the input array to gather subarrays with the same group value, then returns the data to its original structure.
Code: (Demo)
shuffle($data); // randomize all subarrays
foreach ($data as $set) {
$grouped[$set['group']][] = $set; // merge subarrays on group value
}
$output = [];
foreach($grouped as $group) {
array_push($output, ...$group); // return to original array structure
}
var_export($output);
*Note that ... (splat operator) allows array_push() to store all subarrays (within each group) individually to generate the original structure.
Possible Output:
array (
0 =>
array (
'name' => 'Xander',
'group' => 2,
),
1 =>
array (
'name' => 'Giles',
'group' => 2,
),
2 =>
array (
'name' => 'Willow',
'group' => 1,
),
3 =>
array (
'name' => 'Buffy',
'group' => 1,
),
4 =>
array (
'name' => 'Spike',
'group' => 3,
),
5 =>
array (
'name' => 'Tara',
'group' => 3,
),
6 =>
array (
'name' => 'Angel',
'group' => 3,
),
)
Try...
$groups = [];
foreach (array_unique(array_column($myar, 'group')) as $k) $groups[$k] = rand();
foreach (array_keys($myar) as $k) $myar[$k]['rnd'] = rand();
usort($myar, function($a, $b) use ($groups) {
if ($gdif = $groups[$b['group']] - $groups[$a['group']]) return $gdif;
return $b['rnd'] - $a['rnd'];
});
foreach (array_keys($myar) as $k) unset($myar[$k]['rnd']);
print_r($myar);
Run with your data, this is one result...
Array
(
[0] => Array
(
[name] => Buffy
[group] => 1
)
[1] => Array
(
[name] => Willow
[group] => 1
)
[2] => Array
(
[name] => Angel
[group] => 3
)
[3] => Array
(
[name] => Tara
[group] => 3
)
[4] => Array
(
[name] => Spike
[group] => 3
)
[5] => Array
(
[name] => Giles
[group] => 2
)
[6] => Array
(
[name] => Xander
[group] => 2
)
)
I have the following array:
$arr = [
[
'user_id' => 1,
'product_id' => 1
],
[
'user_id' => 1,
'product_id' => 2
],
[
'user_id' => 1,
'product_id' => 3
],
[
'user_id' => 2,
'product_id' => 1
],
[
'user_id' => 2,
'product_id' => 2
],
[
'user_id' => 3,
'product_id' => 1
]
];
And I want to sort it so it looks like this:
$arr = [
[
'user_id' => 1,
'product_id' => 1
],
[
'user_id' => 2,
'product_id' => 1
],
[
'user_id' => 3,
'product_id' => 1
],
[
'user_id' => 1,
'product_id' => 2
],
[
'user_id' => 2,
'product_id' => 2
],
[
'user_id' => 1,
'product_id' => 3
]
];
So basically I need to order by product_id and user_id in such a way that it selects the lower number product_id from each user before proceeding to the next.
I tried to use usort but I couldn't get it to work.
usort($campaigns, function($a, $b){
if($a['product_id'] == $b['product_id']){
return 0;
}
if($a['product_id'] < $b['product_id']){
if($a['user_id'] == $b['user_id']){
return 1;
}
if($a['user_id'] < $a['user_id']){
return 0;
}
return -1;
}else{
if($a['user_id'] == $a['user_id']){
return -1;
}
if($a['user_id'] < $a['user_id']){
return 0;
}
return 1;
}
});
I also tried array_multisort but all I could get it to do is to order using the same order that I already retrieve from the database.
Assumption is your values is integers:
usort($campaigns, function($a, $b){
if($a['product_id'] == $b['product_id']){
return $a['user_id'] - $b['user_id'];
} else {
return $a['product_id'] - $b['product_id'];
}
});
Also you can use database ordering with ORDER BY product_id, user_id clause.
Solution using array_multisort function with "array of columns"(few sorting dimensions):
$userIds = $productIds = [];
foreach ($arr as $k => $v) {
$userIds[$k] = $v['user_id'];
$productIds[$k] = $v['product_id'];
}
array_multisort($productIds, SORT_ASC, $userIds, SORT_ASC, $arr);
print_r($arr);
The output:
Array
(
[0] => Array
(
[user_id] => 1
[product_id] => 1
)
[1] => Array
(
[user_id] => 2
[product_id] => 1
)
[2] => Array
(
[user_id] => 3
[product_id] => 1
)
[3] => Array
(
[user_id] => 1
[product_id] => 2
)
[4] => Array
(
[user_id] => 2
[product_id] => 2
)
[5] => Array
(
[user_id] => 1
[product_id] => 3
)
)
$arrTags = [
[
'user_id' => 1,
'product_id' => 1
],
[
'user_id' => 1,
'product_id' => 2
],
[
'user_id' => 1,
'product_id' => 3
],
[
'user_id' => 2,
'product_id' => 1
],
[
'user_id' => 2,
'product_id' => 2
],
[
'user_id' => 3,
'product_id' => 1
]
];
foreach($arrTags as $key => $row){
$userArray[$key] = $row['user_id'];
$productArray[$key] = $row['product_id'];
}
array_multisort($productArray, SORT_ASC, $userArray, SORT_ASC, $arrTags);
print_r($arrTags);
Output
Array
(
[0] => Array
(
[user_id] => 1
[product_id] => 1
)
[1] => Array
(
[user_id] => 2
[product_id] => 1
)
[2] => Array
(
[user_id] => 3
[product_id] => 1
)
[3] => Array
(
[user_id] => 1
[product_id] => 2
)
[4] => Array
(
[user_id] => 2
[product_id] => 2
)
[5] => Array
(
[user_id] => 1
[product_id] => 3
)
)
You can also check in online editor. Click Here