matching multidimensional arrays by key value, preserving other values - php

I have an array that contains data in the following format:
$myArray = array(
array(
'id' = 1,
'title' = 'the first entry',
'data' = 'additional data'
),
array(
'id' = 2,
'title' = 'the third entry',
'data' = 'some more data'
),
array(
'id' = 3,
'title' = 'the second entry',
'data' = 'other important stuff'
)
);
(An array containing about 12 child arrays in total). This data needs to be split into two rows for displaying on my page, based on the title attribute. I know what titles I want on the first row, and which ones for the second row. So I have another array like this:
$firstRow = array('the first entry', 'the second entry');
$secondRow = array('the third entry');
So what I need to do is throw these 3 arrays, $myArray, $firstRow, $secondRow into a function which will output a new ordered array which preserves the other attributes (the id and data keys in my example) like the following:
$newArray = array(
'firstRow' => array(
array(
'id' = 1,
'title' = 'the first entry',
'data' = 'additional data'
),
array(
'id' = 2,
'title' = 'the second entry',
'data' = 'some more data'
)
),
'secondRow' => array(
array(
'id' = 3,
'title' = 'the third entry',
'data' = 'other important stuff'
)
)
);
I have some ideas, and I know there are various functions like array_intersect(), but I'm not sure which is the best to use? Hopefully someone has a quick and easy solution to this. Thanks.

Use a foreach to loop over the titles array, and create a new array inside the loop, depending on the title value:
function groupTitlesintoArrays($myArray, $firstRow, $secondRow) {
$result = array();
foreach ($myArray as $innerArray) {
foreach ($firstRow as $row) {
if ($row == $innerArray['title']) {
$result['firstRow'][] = $innerArray;
}
}
foreach ($secondRow as $row) {
if ($row == $innerArray['title']) {
$result['secondRow'][] = $innerArray;
}
}
}
return $result;
}
Demo

Related

Search in php multidimensional array

I have a hierarchical array in my project like this:
$Array = array(
array(
'Id' => 1,
'Title' => 'Some Text1',
'Children' => array(
array(
'Id' => 11,
'Title' => 'Some Text11',
'Children' => array(
array(
'Id' => 111,
'Title' => 'Some Text111',
),
array(
'Id' => 112,
'Title' => 'Some Text112',
'Children' => array(
array(
'Id' => 1121,
'Title' => 'Some Text1121',
)
)
)
)
),
array(
'Id' => 12,
'Title' => 'Some Text12',
'Children' => array(
array(
'Id' => 121,
'Title' => 'Some Text121',
)
)
)
)
),
array(
'Id' => 2,
'Title' => 'Some Text2',
)
);
I want to search my string (such as 'Some Text1121') in 'Title' index in this array and return it's path such as after search 'Some Text1121' I want to return this result:
"1 -> 11 -> 112 -> 1121"
Or when I Search 'Some' string, return all path in array.
please help me, thanks.
I've quickly written you something. It's not perfect, but you get the idea:
<?php
function searchRec($haystack, $needle, $pathId = Array(), $pathIndex = Array()) {
foreach($haystack as $index => $item) {
// add the current path to pathId-array
$pathId[] = $item['Id'];
// add the current index to pathIndex-array
$pathIndex[] = $index;
// check if we have a match
if($item['Title'] == $needle) {
// return the match
$returnObject = new stdClass();
// the current item where we have the match
$returnObject->match = $item;
// path of Id's (1, 11, 112, 1121)
$returnObject->pathId = $pathId;
// path of indexes (0,0,1,..) - you might need this to access the item directly
$returnObject->pathIndex = $pathIndex;
return $returnObject;
}
if(isset($item['Children']) && count($item['Children']>0)) {
// if this item has children, we call the same function (recursively)
// again to search inside those children:
$result = searchRec($item['Children'], $needle, $pathId, $pathIndex);
if($result) {
// if that search was successful, return the match-object
return $result;
}
}
}
return false;
}
// useage:
$result = searchRec($Array, "Some Text11");
var_dump($result);
// use
echo implode(" -> ", $result->pathId);
// to get your desired 1 -> 11 -> 112
EDIT: rewritten to make the function actually return something. It now returns an Object with the matching item, the path of Id's and the path of (array-) Indexes.

Adding data to array through loop php

I have a problem where I am getting data from database and need to put that in an array. The array is associative and I am not sure about this practice so I thought I should ask the community. Is this the correct way of adding data to array? The array is for the radio buttons that will be provided to the helper class in prestashop. The array structure is important. This is the var_dump array structure which I have in $options_break2.
$options_value = array();
$options = array();
for($z=0; $z<sizeof($options_break2); $z++)
{
$options_value = array_push($options_value,
array(
"id" => $options_break2[$z],
"name" => $options_break2[$z],
"label" => $options_break2[$z],
)
);
}
$options = array_push($options, $options_value);
What I want is that the array should contain something like:
$example = array(
array(
'id_option' => 'some value',
'name' => 'some value',
),
array(
'id_option' => 'some value',
'name' => 'some value',
),
);
Actually you don't need to use array_push and array() if your PHP version is above 5.6, and you can improve your loop by using the foreach loop:
$options_value = [];
foreach ($options_break2 as $opt) {
$options_value[] = [
"id_option" => $opt, // some_value
"name" => $opt // some_value
];
}
$options = $options_value; // you don't really need this

Get keys from multidimentional array by value

I need to get all "top level" keys from multidimensional array by searching the "bottom level" values. Here is an example of the array:
$list = array (
'person1' => array(
'personal_id' => '1',
'short_information' => 'string',
'books_on_hand' => array(
'Book 1',
'Book 2',
'Book 3',
)
),
'person2' => array(
'personal_id' => '2',
'short_information' => 'string',
'books_on_hand' => array(
'Book 4',
'Book 2',
'Book 5',
)
),
'person3' => array(
'personal_id' => '3',
'short_information' => 'string',
'books_on_hand' => array(
'Book 4',
'Book 2',
'Book 1',
'Book 3',
)
),
//etc...
);
I want to know all persons who have "Book 2" on hand. I can get that information by loop like this:
foreach ($list as $person => $info){
$check = array_search( 'Book 2', array_column($info, 'books_on_hand') );
if ( $check !== false ){
$results .= 'Name: '.$person;
$results .= 'ID: '.$info['personal_id'];
//get other infos other stuff, if necessary
}
}
The problem is, that foreach in this case is very heavy on memory and only grows more when array has a thousand+ entries. It needs to run through all of the persons, even if only 3 persons at the very top of the array have "Book 2".
I have been trying to optimize it by getting persons with "Book 2" using built-in functions like array_search, array_keys, array_column and only then run foreach for persons found, but I had no luck with getting "top level" keys.
Is it possible to optimize or use built-in function to search multidimensional array?
One way would be to filter it first. Now your result is structured like $list but it only contains elements with the needed book:
$find = 'Book 2';
$result = array_filter($list, function($v) use($find) {
return in_array($find, $v['books_on_hand']);
});
If all you're interested in is the person key and personal_id then this:
$find = 'Book 2';
$result = array_map(function($v) use($find) {
if(in_array($find, $v['books_on_hand'])) {
return $v['personal_id'];
}
}, $list);
Will return something like this for persons with the needed book:
Array
(
[person1] => 1
[person2] => 2
[person3] => 3
)

Counting items in each category of a multidimensional array

I have a multidimensional array and I need to count how many items are in each category:
array (
array(
'name' => 'Bob',
'category' => '2'
),
array(
'name' => 'Bill',
'category' => '6'
),
array(
'name' => 'John',
'category' => '1'
),
array(
'name' => 'Jack',
'category' => '2'
),
)
I want to be able to split these up into categories.
For example;
Category 2 contains 2 items
Category 1 contains 1 item
Category 6 contains 1 item
Just to get the count of each category would be great, but to be able to re-arrange the array into categories would also be useful. I'd like to be able to do both.
I've tried searching StackOverflow but I couldn't find this specific query. I'm guessing this may use array_map somewhere but I'm not good with that function.
Any help is greatly appreciated!
If your array isn't too big a straightforward approach might be the easiest one. Create a new array, use categories as keys and iterate over your array, counting items.
I have written 3 functions that solves the criteria you have described. Keep in mind these functions are bare minimum and lack error handling. It is also assumed the $categories array which all the functions requires has the structure outlined in your question.
The first rearranges all items into the correct category.
function rearrangeCategories(array $categories) {
$calculated = [];
foreach($categories as $category) {
$calculated[$category['category']][] = $category['name'];
}
return $calculated;
}
The second creates an associative array of the amount of items in each category. The array index is the category name/id and the value is an integer declaring the amount of items.
function categoriesCount(array $categories) {
$calculated = [];
$arranged = rearrangeCategories($categories);
foreach($arranged as $category => $values) {
$calculated[$category] = count($values);
}
return $calculated;
}
The third function checks how many items are stored inside a specific category. If the category doesn't exists FALSE is returned. Otherwise an integer is returned.
function categoriesItemCount(array $categories, $key) {
$arranged = rearrangeCategories($categories);
if(!array_key_exists($key, $arranged)) {
return false;
}
return count($arranged[$key]);
}
I hope this helps, happy coding.
You can use something like this
$arr =
array (
array(
'name' => 'Bob',
'category' => '2'
),
array(
'name' => 'Bill',
'category' => '6'
),
array(
'name' => 'John',
'category' => '1'
),
array(
'name' => 'Jack',
'category' => '2'
),
);
$categoryCount = array();
$categoryList = array();
array_map(function($a) use (&$categoryCount, &$categoryList) {
$categoryId = $a['category'];
if (!isset($categoryCount[$categoryId])) {
$categoryCount[$categoryId] = 0;
}
$categoryCount[$categoryId]++;
if (!isset($categoryList[$categoryId])) {
$categoryList[$categoryId] = array();
}
$categoryList[$categoryId][] = $a['name'];
}, $arr);
print_r($categoryCount);
print_r($categoryList);
This will create 2 arrays: one with the counts and one with the elements rearranged
Try this way, i think it will fulfill your requirements.
$arr=array (
array(
'name' => 'Bob',
'category' => '2'
),
array(
'name' => 'Bill',
'category' => '6'
),
array(
'name' => 'John',
'category' => '1'
),
array(
'name' => 'Jack',
'category' => '2'
),
);
$result = call_user_func_array('array_merge_recursive', $arr);
//for just show array
print '<pre>';
print_r(array_count_values($result['category']));
print '</pre>';
//loop as you need
foreach(array_count_values($result['category']) as $k=>$v){
$item=($v>1)? 'items':'item';
echo "Category ".$k." Contains " .$v." ".$item."<br/>";
}

Inserting a multidimensional array into another multidimensional array

$stack = array(
'name' => 'some data',
'caption' => 'some data',
'published' => 'some data',
'updated_at' => 'some data',
'updated_by' => 'some data'
);
$data = array('album_id' => 'someID');
How do i insert the data array into the stack array?
update: i tried array_unshift but it inserted the $data array in a second dimension within the multi but i want it at the same level as the others.
also, one more question
if I have another array like data and i want to insert it into the 3rd position how would i do that?
Try
$stack = $stack + $data;
Or
$stack =array_merge($stack, $data);
If you want to add $data to the 3rd position in $stack
$chunks = array_chunk($stack, 2, true);
$stack = array_shift($chunks);
$stack += $data;
foreach ($chunks as $chunk) { $stack += $chunk; }

Categories