PHP Increment array keys +1 - php

I'm looking for some simple solution (1 line) to increment all the keys +1 in an multi array.
Array (
0 => Array (
7 => 'foo',
13 => 'foo'
),
1 => Array (
2 => 'foo',
25 => 'foo'
),
4 => Array (
24 => 'foo'
)
)
RESULT ARRAY
Array (
1 => Array (
8 => 'foo',
14 => 'foo'
),
2 => Array (
3 => 'foo',
26 => 'foo'
),
5 => Array (
25 => 'foo'
)
)

$data = [
0 => [7 => 'foo', 13 => 'foo'],
1 => [2 => 'foo', 25 => 'foo'],
4 => [24 => 'foo'],
];
// top level
$data = array_combine(
array_map(function ($key) { return ++$key; }, array_keys($data)),
$data
);
// then the elements (use array_walk_recursive() if you have more levels)
array_walk(
$data,
function(&$data) {
$data = array_combine(
array_map(function ($key) { return ++$key; }, array_keys($data)),
$data
);
}
);
var_dump($data);
Demo

I'm not sure about a one-liner, especially since you have a multidimensional array. However, this is how I would do it. Honestly, all that one-liner elegance will just make things more complicated for you anyway. It's better to go with readable code in my humble opinion.
// Example array
$array = array (
0 => array (
7 => 'foo',
13 => 'foo'
),
1 => array (
2 => 'foo',
25 => 'foo'
),
4 => array (
24 => 'foo'
)
);
// My solution to increment each key and nested key
$new = array();
foreach($array as $key => $value) {
foreach($value as $inkey => $inval) {
$value[$inkey+1] = $inval;
unset($value[$inkey]);
}
$new[$key+1] = $value;
}
$array = $new;
// Display the array
echo '<pre>'; print_r($array); echo '<pre/>';

Related

PHP array sum values

I'm having this array:
array(
[1] => Array
(
[1111] => Array
(
[one] => 70
[two] => 7.0
)
)
[2] => Array
(
[1111] => Array
(
[one] => 10
[two] => 2.0
)
)
)
And i want it to sum [one] and [two] of the two different arrays and output an array like this:
Array
(
[1111] => Array (
[one] => 80
[two] => 9.0
)
)
Based on the key "1111"
I have tried with the following
$array = array_values( $array );
$sum_array = [];
foreach ( $array as $k => $sub_array ) {
foreach ( $sub_array as $id => $value ) {
$sum_array[$id] += array_key_exists( $id, $sum_array ) ? $sum_array[$id] += $value : $sum_array[$id] = $value;
$sum_array[$id]['two'] += array_sum( $sum_array[$id]['two'] ) / ( 100 * count( $sum_array[$id]['count'] ) );
}
}
But that gives me only the first value like this:
Array
(
[1111] => Array (
[one] => 70
[two] => 7.0
)
)
Can someone please tell me what i'm doing wrong?
You could use the array_reduce to reduce your array to only one element.
The array_reduce function takes two ( sometime three ) parameters. The first one is the array, the second one is a callback with two parameters , the collector, and the current item. If there is a third parameters to the array_reduce function, it will be used to initialize the collector ( like in our case ).
The function will parse each item and do something with it, the collector will be available at each iteration, that's why we use it to keep information of the data, in our case, it's the sum of the values. Once all the item has been iterated over, the function returns the collector.
<?php
$array = [
[
'1111' => [
'one' => 70,
'two' => 7.0
]
],
[
'1111' => [
'one' => 10,
'two' => 2.0
]
]
];
$output = array_reduce($array, function($collector, $item) {
$collector['1111']['one'] += $item['1111']['one'];
$collector['1111']['two'] += $item['1111']['two'];
return $collector;
}, ['1111' => ['one' => 0, 'two' => 0]]);
var_dump($output);
Here is an approach that uses a recursive merge. In the following when merged John's hours become an array. We then need to sum. As James only has one entry his hours do not become an array so we leave them be.
Hopefully the transitional merge output, will give you an idea of the process:
<?php
$items =
[
[
'john' => [
'hours' => 2,
'tips' => 7
]
],
[
'john' => [
'hours' => 3,
'tips' => 10
]
],
[
'james' => [
'hours' => 8,
'tips' => 0
]
]
];
$output = array_merge_recursive(...$items);
var_export($output);
array_walk($output, function(&$v) {
array_walk($v, function(&$v) {
if(is_array($v))
$v = array_sum($v);
});
});
echo "\nResult: \n";
var_export($output);
Output:
array (
'john' =>
array (
'hours' =>
array (
0 => 2,
1 => 3,
),
'tips' =>
array (
0 => 7,
1 => 10,
),
),
'james' =>
array (
'hours' => 8,
'tips' => 0,
),
)
Result:
array (
'john' =>
array (
'hours' => 5,
'tips' => 17,
),
'james' =>
array (
'hours' => 8,
'tips' => 0,
),
)
$total=0;
array_map(function ($item) use ($total)
{
$total += $item['one'] + $item['two'];
}, $array);
echo $total;
Or difference key
$one = array_sum(array_column($array, 'one'));
$two = array_sum(array_column($array, 'two'));
$resultArray = compact('one','two');
```

PHP Imploding Multidimensional Array

I need to implode an multi-dimensional array in a string using implode, i tried using the array_map shown here: stackoverflow.com but i failed.
Array:
Array (
[0] => Array (
[code] => IRBK1179
[qty] => 1
)
[1] => Array (
[code] => IRBK1178
[qty] => 1
)
[2] => Array (
[code] => IRBK1177
[qty] => 1
)
)
Desired Output:
IRBK1179:1|IRBK1178:1|IRBK1177:1
Use foreach and implode() inner array with : and then implode() new array with |. Try below code.
$arr = Array (
0 => Array ( 'code' => 'IRBK1179','qty' => 1 ),
1 => Array ( 'code' => 'IRBK1178','qty' => 1 ),
2 => Array ( 'code' => 'IRBK1177','qty' => 1 ) );
$newArr = array();
foreach ($arr as $row)
{
$newArr[]= implode(":", $row);
}
echo $finalString = implode("|", $newArr);
Output
IRBK1179:1|IRBK1178:1|IRBK1177:1
Working Online Demo: Click Here
Use explode() to get back array from string.
Try below code.
$finalString = "IRBK1179:1|IRBK1178:1|IRBK1177:1";
$firstArray = explode("|", $finalString);
foreach($firstArray as $key=>$row)
{
$tempArray = explode(":", $row);
$newArray[$key]['code'] = $tempArray[0];
$newArray[$key]['qty'] = $tempArray[1];
}
print_r($newArray);
Output
Array
(
[0] => Array
(
[code] => IRBK1179
[qty] => 1
)
[1] => Array
(
[code] => IRBK1178
[qty] => 2
)
[2] => Array
(
[code] => IRBK1177
[qty] => 1
)
)
Working Demo : Click Here
As i commented out, use the implode and foreach. for inner array use : and for outer array use |.
$str = array();
foreach($arr as $val){
$str[] = implode(":", $val);
}
echo implode("|", $str); //IRBK1179:1|IRBK1178:1|IRBK1177:1
Both other answers given by Frayne and Ruchish are correct.
Here is another alternative using array_map.
$arr = [[ 'code' => 'IRBK1179','qty' => 1 ],
[ 'code' => 'IRBK1178','qty' => 1 ],
[ 'code' => 'IRBK1177','qty' => 1 ]];
echo implode('|', array_map(function ($val) {
return $val['code'].':'.$val['qty'];
}, $arr));
Output:-
IRBK1179:1|IRBK1178:1|IRBK1177:1
Simple solution using array_reduce function:
// $arr is the initial array
$result = array_reduce($arr, function($a, $b){
$next = $b['code'].":".$b['qty'];
return (!$a)? $next : (((is_array($a))? $a['code'].":".$a['qty'] : $a)."|".$next);
});
print_r($result);
The output:
IRBK1179:1|IRBK1178:1|IRBK1177:1
Here is my version:
<?php
$arr = [
0 => ['code' => 'IRBK1179', 'qty' => 1],
1 => ['code' => 'IRBK1178', 'qty' => 1],
2 => ['code' => 'IRBK1177', 'qty' => 1],
];
$str = implode("|", array_map(function ($value) {return implode(":", array_values($value));}, array_values($arr)));
var_dump($str); # "IRBK1179:1|IRBK1178:1|IRBK1177:1"
$array = array (
'0' => array (
'code' => 'IRBK1179',
'qty' => '1'
),
'1' => array (
'code' => 'IRBK1178',
'qty' => '1'
),
'2' => array (
'code' => 'IRBK1177',
'qty' => '1'
)
);
$string ='';
foreach($array as $key=>$value){
$string .= $value['code'].':'.$value['qty'].'|';
}
echo $string;

Move inner array values to parent array, reset keys and change key name to string

I have an array as such:
[0] => Array
(
[0] => 1
[1] => 30
[2] => 33
)
[1] => Array
(
[id] => 5
)
I want to move all values in the [0] index out so they become part of the parent array. So the final outcome would look like such:
[0] => Array
(
[id] => 1
)
[1] => Array
(
[id] => 30
)
[2] => Array
(
[id] => 33
)
[3] => Array
(
[id] => 5
)
As you can see the numerical indexes on [0] have now changed to id
I've tried using array_map('current', $array[0])
to no avail, any suggestions?
You could use the ol' trusty double foreach:
$new_array = array();
foreach ($array as $arr) {
foreach ($arr as $ar) {
$new_array[] = array('id'=>$ar);
}
}
Demo
$data = array(
array(1, 30, 33),
array('id' => 5)
);
$result = array();
array_walk_recursive(
$data,
function($value) use (&$result) {
$result[] = array('id' => $value);
}
);
var_dump($result);
Just to show that iterators can be really useful tools as well:
$data = array(
array(1, 30, 33),
array('id' => 5)
);
$result = array();
foreach (new RecursiveIteratorIterator(
new RecursiveArrayIterator($data),
RecursiveIteratorIterator::LEAVES_ONLY
) as $value) {
$result[] = array('id' => $value);
}
var_dump($result);
$array = [
[1, 30, 33],
['id' => 5]
];
$result = array_reduce($array, function (array $result, array $array) {
return array_merge($result, array_map(
function ($id) { return compact('id'); },
array_values($array)
));
}, []);
var_dump($result);
Admittedly not the simplest way to solve this, but very "functional". ;)
$array = array(
array(0 => 1,1 => 30,2 => 33,),
array("id" => 5,)
);
$result = array_merge(
array_map('array_flip',
array_chunk(
array_fill_keys($array[0], "id"),
1, true)
),
array_slice($array, 1)
);
var_export($result);
Results in:
array (
array ( 'id' => 1 ),
array ( 'id' => 30 ),
array ( 'id' => 33 ),
array ( 'id' => 5 )
)

Removing items from an array based on items in another array

I have 2 arrays:
Array ( [0] => Array ( [intTrackId] => 41 [intAverageRating] => 10 [bolNewRelease] => 0 [dtDateAdded] => 2013-03-08 17:32:26 ) [1] => Array ( [intTrackId] => 1 [intAverageRating] => 7 [bolNewRelease] => 0 [dtDateAdded] => 2013-03-08 18:54:35 ))
Array ( [0] => Array ( [intTrackId] => 41 [intAverageRating] => 5.5000 [bolNewRelease] => 1 [dtDateAdded] => 2014-03-25T09:39:28Q ) [1] => Array ( [intTrackId] => 361 [intAverageRating] => 8.0000 [bolNewRelease] => 1 [dtDateAdded] => 2014-03-25T09:39:28Q ))
I want to remove the items in the second which have a matching track ID in the first. So in this example, I would get:
Array ( [0] => Array ( [intTrackId] => 361 [intAverageRating] => 8.0000 [bolNewRelease] => 1 [dtDateAdded] => 2014-03-25T09:39:28Q ))
Is this possible with array_filter or is this a little complex for that?
Just use array_udiff() - it's intended to do this:
$one = Array (
0 => Array ('intTrackId' => 41, 'intAverageRating' => 10, 'bolNewRelease' => 0, 'dtDateAdded' => '2013-03-08 17:32:26' ),
1 => Array ('intTrackId' => 1, 'intAverageRating' => 7, 'bolNewRelease' => 0, 'dtDateAdded' => '2013-03-08 18:54:35' )
);
$two = Array (
0 => Array ('intTrackId' => 41, 'intAverageRating' => 5.5000, 'bolNewRelease' => 1, 'dtDateAdded' => '2014-03-25T09:39:28Q' ),
1 => Array ('intTrackId' => 361, 'intAverageRating' => 8.0000, 'bolNewRelease' => 1, 'dtDateAdded' => '2014-03-25T09:39:28Q' )
);
$result = array_udiff($two, $one, function($x, $y)
{
return $x['intTrackId']-$y['intTrackId'];
});
Yes it can be done with array_filter:
$array1 = array(...);
$array2 = array(...);
$newArray = array_filter($array2, function($item) use ($array1){
foreach($array1 as $elem){
if($item['intTrackId'] == $elem['intTrackId']){
return false;
}
}
return true;
});
I would first create a loop and store all track IDs from the first array in a separate array.
Then I'd loop over the second array and delete those keys that exist in the track ID array.
$track_ids = array();
foreach($array1 as $index => $items) {
$track_ids[$items['intTrackId']] = $index;
}
foreach($array2 as $items) {
if (isset($track_ids[$items['intTrackId']])) {
unset($array2[$track_ids[$items['intTrackId']]]);
}
}

Change index of an array

I want to change the index of an array but I don't know how to do it..
The following array
array(
0 => array ( 'id' => 33, 'name' => 'test' )
1 => array ( 'id' => 37, 'name' => 'test2' )
)
should become - if i want the index
array(
33 => array ( 'id' => 33, 'name' => 'test' )
37 => array ( 'id' => 37, 'name' => 'test2' )
)
or if i want the name
array(
test => array ( 'id' => 33, 'name' => 'test' )
test2 => array ( 'id' => 37, 'name' => 'test2' )
)
also for a multi-dimensional array
array(
0 => array ( 'id' => 33, 'details' => array (name => 'test' , age ='50' ) )
1 => array ( 'id' => 37, 'details' => array (name => 'test2' , age ='60' ) )
)
to index replace 0 and 1 with the name - test or test2
right now I made a function but is not working with multi dimensional arrays
function index_array( $array, $index ){
$new_array = array();
foreach($array as $key => $value){
$new_array[$index] = $array[$key];
}
return $new_array;
}
$array = array(33 => $oldarray[0], 37 => $oldarray[1]);
$array = array('test' => $oldarray[0], 'test2' => $oldarray[1]);
Since the right-hand-side of the expression is evaluated before the assignment you could also use $array on both sides instead of a different variable name.
I'd do it with a mapping table for the first part, or a simple foreach for the second part:
<?php
$arr = array(
0 => array( 'id' => 33, 'name' => 'test' ),
1 => array( 'id' => 37, 'name' => 'test2' )
);
/* Convert to other indexes */
$mapping = array(
0 => 33,
1 => 37
);
foreach($arr as $k => $v){
unset($arr[$k]);
$arr[$mapping[$k]] = $v;
}
print_r($arr);
/* Convert key to name field */
foreach($arr as $k => $v){
unset($arr[$k]);
$arr[$v['name']] = $v;
}
print_r($arr);
EDIT: Now that I read your question again, the first part is actually the same as the second, but then just with the id field instead of the name field.
EDIT2: Note that you'd have to use another array to write to, to avoid overrides, which will occur when the id field is used as a replacement.

Categories