I have an associative array with indexed sub-arrays each containing associative arrays which contain content and an index. So like this (in PHP):
$assoc_arr =
array("second" => array(
array("position" => 4,
"content" => "Valiant"),
array("position" => 5,
"content" => "Hail")
),
"first" => array(
array("position" => 0,
"content" => "Hail"),
array("position" => 3,
"content" => "Victors"),
array("position" => 2,
"content" => "the"),
array("position" => 1,
"content" => "to")
)
);
I want to put all of those into an indexed array where their index is their "position" in the associative array. So final array should be:
Array ( [0] => Hail [1] => to [2] => the [3] => Victors [4] => Valiant [5] => Hail )
Currently, I'm merging all of the arrays inside the highest level array, then sorting it by each of those sub-array's positions, then creating an indexed array by pushing the content in order onto a new array. As so:
$pos_arr = array_merge($assoc_arr["second"], $assoc_arr["first"]);
usort($pos_arr, function($a, $b) {
return $a["position"] >= $b["position"] ? 1 : -1;
});
$indexed_arr = array();
foreach ($pos_arr as $elem) {
array_push($indexed_arr, $elem["content"]);
}
It seems like there must be a better way to do this! Can anyone think of one?
The data is coming from a poorly structured XML document which I can't change.
$idxar=array();
foreach ($assoc_arr as $subar)
foreach ($subar as $item)
$idxar[$item['position']+0]=$item['content'];
will work, if your input data is flawless.
Edit
If you need the keys not only to be numerically correct, but also in the correct order, you must suffix this with ksort($idxar)
here is another solution:
<?php
$assoc_arr =
array("second" => array(
array("position" => 4,
"content" => "Valiant"),
array("position" => 5,
"content" => "Hail")
),
"first" => array(
array("position" => 0,
"content" => "Hail"),
array("position" => 3,
"content" => "Victors"),
array("position" => 2,
"content" => "the"),
array("position" => 1,
"content" => "to")
)
);
$order = array('first','second'); // this helps you create your own sort. E.g. position1, position2, etc
$arr = array();
foreach($order as $ord) {
if(isset($assoc_arr[$ord])) {
$arr = array_merge($arr, $assoc_arr[$ord]);
}
}
$finalArray = array();
foreach($arr as $a) {
$finalArray[$a['position']] = $a['content'];
}
ksort($finalArray);
print_r($finalArray);
and a fiddle that works for you here
Related
How can I use the php array_multisort to sort arrays like this? I can't find any examples with this type of arrays. I have tried different avenues but I keep getting the error array_multisort(): Array sizes are inconsistent.
$array= Array (
"Arnold" => Array ( "index" => 2, "games_played" => 1, "score" => 5 ),
"Chris" => Array ( "index" => 1, "games_played" => 1, "score" => 5 ),
"Mike" => Array ( "index" => 0, "games_played" => 2, "score" => 5 )
);
I think you're taking it the wrong way. array_multisort is not what would be a "sort by" in other languages (i.e: sort array elements by some properties), instead it sorts the first array, and reverberate that order to all following arrays. And in case of equality it checks the corresponding values of the second arrays, etc...
If you want to order your example by score (desc), then by game played, then by index (and then by name, but this should never happen since indexes are uniques) you should do:
$array= Array (
"Arnold" => Array ( "index" => 2, "games_played" => 1, "score" => 5 ),
"Chris" => Array ( "index" => 1, "games_played" => 1, "score" => 5 ),
"Mike" => Array ( "index" => 0, "games_played" => 2, "score" => 5 )
);
$names = [];
$indexes = [];
$games_played = [];
$scores = [];
foreach ($array as $name => $player) {
$names[] = $name;
$indexes[] = $player['index'];
$games_played[] = $player['games_played'];
$scores[] = $player['score'];
}
array_multisort(
$scores, SORT_DESC,
$games_played,
$indexes,
$names,
$array /* This line will sort the initial array as well */
);
I would like to merge the associative elements from my second array into my first array where the second array's subarray key matches a row's epg_channel_id value.
First array:
[
[
'num' => 1,
'name' => 'name 1',
'epg_channel_id' => 'ch111',
'added' => '1505435915',
],
[
'num' => 2,
'name' => 'name 2',
'epg_channel_id' => 'ch222',
'added' => '1505435915',
],
[
'num' => 3,
'name' => 'name 3',
'epg_channel_id' => 'ch333',
'added' => '1505435915',
],
[
'num' => 4,
'name' => 'name 4',
'epg_channel_id' => 'ch444',
'added' => '1505435915'
]
]
And the second array:
[
['ch000' => 'Um9jayBJbiBSaW8='],
['ch111' => 'Um9jayBJbiBSaW8='],
['ch222' => 'Um9jayBJbiBSaW8='],
['ch333' => 'Um9jayBJbiBSaW8='],
['ch444' => 'Um9jayBJbiBSaW8=']
]
Desired output (for one row):
Array
(
[0] => Array
(
[num] => 1
[name] => name 1
[epg_channel_id] => ch111
[added] => 1505435915
[ch111] => Um9jayBJbiBSaW8=
)
...
)
I tried array_recursive, array merge and not works.
If the corresponding indexes in both arrays are guaranteed to have the same channel id, this will work quite efficiently. For example, if $array1[0] is guaranteed to have the same channel id as $array2[0] this solution will work nicely:
$combined = [];
foreach($array1 as $key=>$val){
$combined[$key] = $val + $array2[$key];
}
However, if the corresponding indexes are not guaranteed to have the same channel ids, this solution will not work, and you'll need to use one of the other posted answers.
One last note if you do use this method is that if the arrays are different sizes, you will want the largest one to be $array1. So, just do a comparison to see which has the most elements.
You have to loop over two arrays to get desired result: as you have to match epg_channel_id of first array to second arrays inner key
$arr1 = Array
(
0 => Array
(
"num" => 1,
"name" => "name 1",
"epg_channel_id" => "ch111",
"added" => "1505435915",
),
1 => Array
(
"num" => 2,
"name" => "name 2",
"epg_channel_id" => "ch222",
"added" => "1505435915",
),
2 => Array
(
"num" => 3,
"name" => "name 3",
"epg_channel_id" => "ch333",
"added" => "1505435915",
),
3 => Array
(
"num" => 4,
"name" => "name 4",
"epg_channel_id" => "ch444",
"added" => "1505435915",
),
);
$arr2 = Array
(
0 => Array
(
"ch000" => "Um9jayBJbiBSaW8="
),
1 => Array
(
"ch111" => "Um9jayBJbiBSaW8="
),
2 => Array
(
"ch222" => "Um9jayBJbiBSaW8="
),
3 => Array
(
"ch333" => "Um9jayBJbiBSaW8="
),
4 => Array
(
"ch444" => "Um9jayBJbiBSaW8="
),
);
$new_array = array();
foreach($arr1 as $key=>$value)
{
foreach($arr2 as $key1=>$value1)
{
foreach($value1 as $key2=>$value2)
{
if($key2 == $value['epg_channel_id'])
{
$value[$key2]=$value2;
}
}
}
$new_array[$key]=$value;
}
print_r($new_array);
DEMO
You can key exists or not using array_key_exists in second array then add it to new array
Working Demo: https://eval.in/863359
$array = Array
(
Array
(
'num' => 1,
'name' => 'name 1',
'epg_channel_id' => 'ch111',
'added' => '1505435915',
),
Array
(
'num' => 2,
'name' => 'name 2',
'epg_channel_id' => 'ch222',
'added' => '1505435915',
),
Array
(
'num' => 3,
'name' => 'name 3',
'epg_channel_id' => 'ch333',
'added' => '1505435915',
),
Array
(
'num' => 4,
'name' => 'name 4',
'epg_channel_id' => 'ch444',
'added' => '1505435915'
)
);
$array2 = Array
(
Array
(
'ch000' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch111' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch222' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch333' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch444' => 'Um9jayBJbiBSaW8='
)
);
$newArray =[];
foreach ($array as $key => $value) {
foreach ($array2 as $key2 => $value2) {
if (array_key_exists($value['epg_channel_id'], $value2)) {
$value[$value['epg_channel_id']] = $value2[$value['epg_channel_id']];
}
}
$newArray[] = $value;
}
echo "<pre>";
print_r($newArray);
array_merge_recursive works well for associated array that have keys are string. Numeric keys will be appended. From php.net
If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.
You have to convert your array to string keys, or using one loop to merge child arrays one by one.
Try this . I hope it will solve your problems. I have tested it.
foreach ($array1 as $key => $value){
// echo $key;
foreach ($array2 as $i =>$item){
foreach ($item as $j=>$subitem){
if($value['epg_channel_id'] == $j){
$array1[$key][$j] = $subitem;
}
}
}
}
print_r($array1);
try to read the value of 'epg_channel_id' from array1
and insert it to array1 itself from getting 'ch111' from array2
$ch_name = $array1[$i]['epg_channel_id'];
$id = $array1[$i]['num'];
$ch_value = $array2[$id]['$ch_name'];
$array1[$i]["$ch_name"] = $ch_value;
try to put in foreach for every array
$new_arr = [];
foreach($arr1 as $val){
foreach($arr2 as $val2){
if(array_key_exists($val['epg_channel_id'], $val2)){
$val[$val['epg_channel_id']] = $val2[$val['epg_channel_id']];
break;
}
}
$new_arr[] = $val;
}
print_r($new_arr);
The bad news is that your second array is not suitably structured to serve as a lookup array. The good news is that the step to flatten the structure into a simple associative array is quite easy.
Once the lookup is declared, just use a loop and modify-by-reference as you use array union syntax to append the desired key-value pairs.
I do not recommend any answers that are using nested loops -- they will not perform efficiently.
Code: (Demo)
$lookup = array_merge(...$array2);
foreach ($array as &$row) {
$row += [$row['epg_channel_id'] => $lookup[$row['epg_channel_id']]];
}
var_export($array);
This question already has an answer here:
Convert value from specific multidimensional array key into key in new array with original arrays as value
(1 answer)
Closed 5 months ago.
What's the easiest way to convert
$a = array(
array("id" => 1, "name" => "a1"),
array("id" => 2, "name" => "a2")
);
to
$b = array(
"a1" => array("id" => 1, "name" => "a1"),
"a2" => array("id" => 2, "name" => "a2")
);
I was expecting PHP have some functional programming facilities to do something like:
$b = map($a, function($item) {
return $item["name"];
});
But I didn't find one.
You can use PHP array_column() function. For your use case, the second argument should be null to return the full array.
$a = array(
array("id" => 1, "name" => "a1"),
array("id" => 2, "name" => "a2")
);
$b = array_column($a, null, 'name');
and print_r($b) will result in
Array
(
[a1] => Array
(
[id] => 1
[name] => a1
)
[a2] => Array
(
[id] => 2
[name] => a2
)
)
The only solution I see is to loop through the array and create a new array manually.
For example, like this:
$new_array = [];
foreach ($array as $value)
$new_array[$value['name']] = $value;
You can simply do this
$input = [
["id" => 1, "name" => "a1"],
["id" => 2, "name" => "a2"]
];
$result = array_merge(
...array_map(
fn($item) => [$item['name'] => $item],
$input
)
);
Poor me need to implement this in PHP 5.2, and I do not want to use for loop
here's my implementation:
function getField($x) { return $x['name']; }
$ids = array_map('getField', $result);
$result = array_combine($ids, $result);
See if maybe this helps anybody lol
The accepted answer is close, but "close" only counts with hand grenades.
($unique is an indexed array)
$sub_key = 'country';
$new_array = [];
foreach ($unique as $value) {
$new_array[] = [$sub_key => $value];
}
How about:
$a = array(
array('a' => 'a0', 'b' => 'b0', 'c' => 'c0'),
array('a' => 'a1', 'b' => 'b1', 'c' => 'c1'),
array('a' => 'a2', 'b' => 'b2', 'c' => 'c2'),
);
print_r($a);
print_r(array_combine(array_column($a, 'a'), $a));
Where 'a' is the column to use as the associative index.
This leaves the column that becomes the index in the array.
array_column (PHP 5 >= 5.5.0, PHP 7)
array_combine (PHP 5, PHP 7)
I have 2 arrays, 1 holds the data to be displayed and the other holds the order.
the following array will be used in a foreach loop to display:
array(
[Posts] =>
[0] =>
id => 7
content => 'some content'
[1] =>
id => 3,
content => 'some other content'
[2] =>
id => 4,
content => 'some more content'
[3] =>
id => 2,
content => 'some irrelevant content'
)
This array contains the sort positions:
array(
2, 4, 7, 3
)
I would like to sort the first array based on the vaulue in the associative array where the key is id that matches the second array.
Expected output:
array(
[Posts] =>
[0] =>
id => 2,
content => 'some irrelevant content'
[1] =>
id => 4,
content => 'some more content'
[2] =>
id => 7
content => 'some content'
[3] =>
id => 3,
content => 'some other content'
)
You'd significantly help yourself if source array keys would be equal to Ids. That'd speed things up. But for now this would make your source data ordered accoring to your sort array values):
$res = array();
foreach( $sortArray as $sortId ) {
foreach( $srcArray as $item ) {
if( $item['id'] == $sortId ) {
$res = $item;
break;
}
}
}
EDIT
if you'd have Id used as keys, then second foreach() would be of no use:
$res = array();
foreach( $sortArray as $sortId ) {
$res[] = $srcArray[ $sortId ];
}
This solution uses usort:
$sarray = array(2, 4, 7, 3);
$sarray = array_flip($sarray);
usort($posts, function($a, $b) use($sarray) {
// TODO: check if the array-index exists ;)
$index_a = $sarray[$a['id']];
$index_b = $sarray[$b['id']];
return $index_a - $index_b;
});
var_dump($posts);
Since I'm using closures you need PHP 5.3 to use it like that. If you need to have 5.2 compatibility, you probably have to use create_function.
I currently have an array, created from a database, an example of which looks like the following:
Array(
[0] => Array (
objectid => 2,
name => title,
value => apple
),
[1] => Array (
objectid => 2,
name => colour,
value => red
),
[2] => Array (
objectid => 3,
name => title,
value => pear
),
[3] => Array (
objectid => 3,
name => colour,
value => green
)
)
What I would like to do is group all the items in the array by their objectid, and convert the 'name' values into keys and 'value' values into values of an associative array....like below:
Array (
[0] => Array (
objectid => 2,
title => apple,
colour => red
),
[1] => Array (
objectid => 3,
title => pear,
colour => green
)
)
I've tried a few things but haven't really got anywhere.. Any ideas?
Thanks in advance
This should work with your current setup and should be able to handle as many key-value pairs as available:
<?php
$results = array(
array('objectid' => 2, 'name' => 'title', 'value' => 'apple'),
array('objectid' => 2, 'name' => 'color', 'value' => 'red'),
array('objectid' => 3, 'name' => 'title', 'value' => 'pear'),
array('objectid' => 3, 'name' => 'color', 'value' => 'green'));
$final = array();
foreach ($results as $result) {
$final[$result['objectid']]['objectid'] = $result['objectid'];
$final[$result['objectid']][$result['name']] = $result['value'];
}
print_r($final);
It would be easier to have the array keys correspond with your object id, that way you can iterate through your existing array, and add the key-value pairs for each object, like so:
$newArray = array();
foreach ($results as $result) {
if (!array_key_exists($result['objectid'], $newArray)) {
$newArray[$result['objectid'] = array();
}
foreach ($result as $key => $value) {
$newArray[$result['objectid'][$key] = $value;
}
}
Peter's method is perfectly valid, I just thought I would show a shorter version of the same thing (couldn't do in a comment)
foreach( $array as $obj ) {
if( !isset( $objects[$obj['objectid']] ) )
$objects[$obj['objectid']]['objectid'] = $obj['objectid'];
$objects[$obj['objectid']][$obj['name']] = $obj['value'];
}