php multidimensional array count dynamically - php

I have two arrays $users and $find. I need count how many matches in $users if $find array would be changed.
$users = array(
[
'name' => 'Jim',
'sname' => 'Carrey'
],
[
'name' => 'Michael',
'sname' => 'Douglas'
],
[
'name' => 'Michael',
'sname' => 'Jackson'
],
[
'name' => 'Michael',
'sname' => 'Jordan'
]
);
Find array changed dynamically. It may be:
$find = array (
'name' => array('Michael'),
'sname' => array('Douglas', 'Jordan')
);
OR:
$find = array (
'sname' => array('Carrey', 'Jordan')
);
I'm looking for a one-size-fits-all solution for for any values in $find array.
Thanks!
I can count if I have static keys and values in $find array:
$result = array_filter($users, function($user) {
return in_array($user['name'], ['Michael', 'Jim']) && in_array($user['sname'], ['Douglas', 'Jordan', 'Carrey']);
});
$count = count($result);
print_r($result);
But I don't understand how count if it should be dynamic keys and values in $find array.

If you want to deal with an unknown number of items in $find, then you will need to loop over them. The use keyword helps to "inject" $find into your callback function. In your loop, you can return false, if the in_array check for the current find item results in false, otherwise you return true after the loop.
$result = array_filter($users, function($user) use ($find) {
foreach($find as $col => $values) {
if(!in_array($user[$col], $values)) {
return false;
}
}
return true;
});

$result=array_intersect($users,$find);
print_r($result);

Related

Loop multidimensional line by line

I'm trying to loop through this array to output side by side for every iteration.
$cars = [
'BMW' => [
'Year' => '2020',
'Body' => 'Sedan',
'Mileage' => '100'
],
'Ford' => [
'Year' => '2019',
'Body' => 'SUV',
'Mileage' => '500'
]
];
$count = count(reset($cars));
for($i=0; $i<$count; $i++) {
foreach($cars as $key => $value) {
echo $cars[$key][$i]. '<br>';
}
}
My expected result for every iteration.
2020,2019
Sedan,SUV
100,500
I have searched through some links, but none is specific to a multidimensional array.
Two arrays in foreach loop
How can I loop through two arrays at once?
The other question you point to is about having separate arrays of data, which you could sort of emulate by splitting the main array into parts.
This solution assumes that all of the keys for the values you want are in the first item (as in your example, they all have the 3 values) and loops over the first array element and uses array_column() to extract all of the values from all of the main array elements for that key. Then implode() these values to put them as a CSV list...
foreach ( $cars[array_keys($cars)[0]] as $key => $value) {
echo implode(",", array_column($cars, $key)).PHP_EOL;
}
which with your test data gives...
2020,2019
Sedan,SUV
100,500
You can simply do it by storing your desired array values in another array and then implode them or make them work by your need. Take a look at the following code..
$cars = [
'BMW' => [
'Year' => '2020',
'Body' => 'Sedan',
'Mileage' => '100'
],
'Ford' => [
'Year' => '2019',
'Body' => 'SUV',
'Mileage' => '500'
],
];
$year = [];
$body = [];
$milage = [];
foreach( $cars as $key => $car ){
if( $car['Year'] ){
$year[] = $car['Year'];
}
if( $car['Body'] ){
$body[] = $car['Body'];
}
if( $car['Mileage'] ){
$milage[] = $car['Mileage'];
}
}
var_dump(implode( ',', $year));
var_dump(implode( ',', $body));
var_dump(implode( ',', $milage));
will give you output:
string(9) "2020,2019" string(9) "Sedan,SUV" string(7) "100,500"

Remove unwanted elements from subarrays in multidimensional array

I have a multidimensional array like this:
[
[
'id' => 1,
'name' => 'John',
'address' => 'Some address 1'
'city' => 'NY'
],
[
'id' => 2,
'name' => 'Jack',
'address' => 'Some address 2'
'city' => 'NY'
]
...
[ ... ]
]
How can I remove elements in all subarrays and only retain the id and name keys with their values?
Would this work?
$result = array_map(function($arr) {
return [
'id' => $arr['id'],
'name' => $arr['name']
];
}, $orig_array);
You want to retain the first two associative elements, so you can make array_slice() calls within array_map(). (Demo)
var_export(
array_map(fn($row) => array_slice($row, 0, 2), $array)
);
Or mapped called of array_intersect_key() against an establish whitelist array. (Demo)
$keep = ['id' => '', 'name' => ''];
var_export(
array_map(
fn($row) => array_intersect_key($row, $keep),
$array
)
)
Or, you could use array destructuring inside of a classic foreach() and make iterated compact() calls. (Demo)
$result = [];
foreach ($array as ['id' => $id, 'name' => $name]) {
$result[] = compact(['id', 'name']);
}
var_export($result);
If you want to edit the same array in place, you can simply iterate over them and unset them.
<?php
$preserve_keys = ['id','name'];
foreach($arr as &$data){
foreach($data as $key => $value){
if(!in_array($key,$preserve_keys)){
unset($data[$key]);
}
}
}
If you want it as a separate result, loop over and add it to the new array.
<?php
$new_result = [];
foreach($arr as $data){
$new_result[] = [
'id' => $data['id'],
'name' => $data['name']
];
}
print_r($new_result);

Get the index of an array based on keys

I have an array with an index. The index is not static and keeps changing.
$fields = [
11 => array (
'fieldId' => 'ORStreet',
'type' => 'TEXT',
'value' => 'Postbus 52',
),
];
Index of the above one is 11. But sometimes it becomes a different number.
One thing that always stays the same is the fieldId. How can i get the index of this array by only knowing the field id.
This above array is a child of the main array called 'fields'.
In my head i have something like this:
Loop through the main array called fields > if you find an array with fieliD => ORStreet. Return the index of that array.
If its not possible to get an index this way, i wouldnt mind if I got the 'value' => 'Postbus52' key-pair.
<?php
$arr = [
[
'fieldId' => 'ORStreet',
'type' => 'TEXT',
'value' => 'Postbus 52',
],
[
'fieldId' => 'vbnm',
'type' => 'TEXT',
'value' => 'Postbus 52',
],
[
'fieldId' => 'ORStreet',
'type' => 'TEXT',
'value' => 'Postbus 52',
]
];
shuffle($arr);
foreach ($arr as $key => $value) {
if(array_key_exists("fieldId", $value) && $value["fieldId"] === "ORStreet"){
echo $key;
break;
}
}
?>
I have used shuffle method to simulate randomness of the array. Then I have loop through the array to match fieldId with specified value(ORStreet) . If it got match then the loop will terminates and display the index.
Another Way:
$filteredArr = array_pop(array_filter($arr, function ($a){
return array_key_exists("fieldId", $a) && $a["fieldId"] === "ORStreet";
}));
You can use combination of array_map() and array_flip()
$index = array_flip(array_map(function($val){
return $val["fieldId"];
}, $arr));
echo $index["ORStreet"];
// output: 11
Check result in demo
One more possibility:
$result = array_keys(
array_combine(array_keys($fields), array_column($fields, "fieldId")),
"ORStreet"
);
array_column() extracts all the fieldId values, and then array_keys() searches for your desired value, returning the relevant array keys.
Note this will return an array of keys. If you only want the first key, this will return it as an integer:
$result = array_search(
"ORStreet",
array_combine(array_keys($fields), array_column($fields, "fieldId"))
);

push certain elements into array php

I want to know that is there a way to insert certain elements of an array into a new array. I mean I have an array containing 10 objects. Each object has 3 or four fields for example id, name , age , username. now I want to insert the id's of all the objects into the new array with a single call.Is there anyway to do that.
$array = [
[0] => [
id =>
name =>
],
[1] = > [
id =>
name =>
]
]
and so on now I want to insert all the id's of all the object into a new array with a single call. Is there a way to do that?
Use array_map() function.
Here is your solution:-
$ids = array_map( function( $arr ){
return $arr["id"];
}, $arr );
echo '<pre>'; print_r($ids);
A basic foreach loop will do the job just fine
$firstArray = array(
array(
'id' => 1,
'name' => 'abc'
),
array(
'id' => 2,
'name' => 'def'
),
array(
'id' => 3,
'name' => 'gh'
)
);
$onlyIds = array();
$onlyKeys = array();
//To get the array value 'id'
foreach($firstArray as $value){
$onlyIds[] = $value['id'];
}
//To get the array keys
foreach($firstArray as $key => $value){
$onlyKeys[] = $key;
}
You could use array_walk which could be considered a "single call"
$array = array(0 => array('id', 'name', 'age'), 1 => array('id', 'name', 'age'));
array_walk($array, function($item, $key) {
// $key is 0 or 1
// $item is either id, name, age
});
You can use array_column.
$arr = [ ['id' => 1, 'username' => 'a'], ['id' => 2, 'username' => 'b'] ];
$ids = array_column($arr, 'id')
$ids == [1, 2]

Find array elements that have a certain key-name prefix

I have an associative array with lots of elements and want to get a list of all elements that have a key name with a certain prefix.
Example:
$arr = array(
'store:key' => 1,
'user' => 'demo',
'store:foo' => 'bar',
'login' => true,
);
// this is where I need help with:
// the function should return only elements with a key that starts with "store:"
$res = list_values_by_key( $arr, 'store:' );
// Desired output:
$res = array(
'store:key' => 1,
'store:foo' => 'bar',
);
You could simply do :
$arr = array(
'store:key' => 1,
'user' => 'demo',
'store:foo' => 'bar',
'login' => true,
);
$arr2 = array();
foreach ($arr as $array => $value) {
if (strpos($array, 'store:') === 0) {
$arr2[$array] = $value;
}
}
var_dump($arr2);
Returns :
array (size=2)
'store:key' => int 1
'store:foo' => string 'bar' (length=3)
This should work for you:
Just grab all keys which starts with store: with preg_grep() from your array. And then do a simple array_intersect_key() call to get the intersect of both arrays.
<?php
$arr = array(
'store:key' => 1,
'user' => 'demo',
'store:foo' => 'bar',
'login' => true,
);
$result = array_intersect_key($arr, array_flip(preg_grep("/^store:/", array_keys($arr))));
print_r($result);
?>
output:
Array
(
[store:key] => 1
[store:foo] => bar
)
From php 5.6 you can use array_filter:
$return = array_filter($array, function ($e) {
return strpos($e, 'store:') === 0;
}, ARRAY_FILTER_USE_KEY);
var_dump($return);
for earlier versions, you can use
$return = array_intersect_key($array, array_flip(array_filter(array_keys($array), function ($e) {
return strpos($e, 'store:') === 0;
})));
Demo.

Categories