Filter array by its keys using an array of allowed keys
PHP 5.6 introduced a third parameter to array_filter()
, flag
, that you can set to ARRAY_FILTER_USE_KEY
to filter by key instead of value:
$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed = ['foo', 'bar'];
$filtered = array_filter(
$my_array,
function ($key) use ($allowed) {
// N.b. in_array() is notorious for being slow
return in_array($key, $allowed);
},
ARRAY_FILTER_USE_KEY
);
Since PHP 7.4 introduced arrow functions we can make this more succinct:
$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed = ['foo', 'bar'];
$filtered = array_filter(
$my_array,
fn ($key) => in_array($key, $allowed),
ARRAY_FILTER_USE_KEY
);
Clearly this isn't as elegant as array_intersect_key($my_array, array_flip($allowed))
, but it does offer the additional flexibility of performing an arbitrary test against the key, e.g. $allowed
could contain regex patterns instead of plain strings.
You can also use ARRAY_FILTER_USE_BOTH
to have both the value and the key passed to your filter function. Here's a contrived example based upon the first, but note that I'd not recommend encoding filtering rules using $allowed
this way:
$my_array = ['foo' => 1, 'bar' => 'baz', 'hello' => 'wld'];
$allowed = ['foo' => true, 'bar' => true, 'hello' => 'world'];
$filtered = array_filter(
$my_array,
fn ($val, $key) => isset($allowed[$key]) && (
$allowed[$key] === true || $allowed[$key] === $val
),
ARRAY_FILTER_USE_BOTH
); // ['foo' => 1, 'bar' => 'baz']
Filter an array of objects with keys
you can do this:
array.filter((item)=>{return item.someKey==='valueYouWant'})
in your example you can do something like this:
const filtered=array.filter((item)=>{return item.categoryId<22})
How to filter array when object key value is in array
You can do it with Array.prototype.filter()
,
var data = { records : [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }] }
var empIds = [1,4,5]
var filteredArray = data.records.filter(function(itm){
return empIds.indexOf(itm.empid) > -1;
});
filteredArray = { records : filteredArray };
If the callBack
returns a true
value, then the itm
passed to that particular callBack
will be filtered out. You can read more about it here.
Filter object properties by key in ES6
If you have a list of allowed values, you can easily retain them in an object using:
const raw = { item1: { key: 'sdfd', value:'sdfd' }, item2: { key: 'sdfd', value:'sdfd' }, item3: { key: 'sdfd', value:'sdfd' }};
const allowed = ['item1', 'item3'];
const filtered = Object.keys(raw) .filter(key => allowed.includes(key)) .reduce((obj, key) => { obj[key] = raw[key]; return obj; }, {});
console.log(filtered);
Use an array of keys to filter another array, keeping the order
Pretty simple
$data = [
'title' => 'loops and things',
'id' => '28fr2',
'link' => 'https://blah',
'itemid' => '28fr3',
'quantity' => 3,
//...
];
$product = [
'id',
'title',
'link'
];
$res = array_merge(array_fill_keys($product, null),array_intersect_key($data, array_flip($product)));
print_r($res);
Output
Array
(
[id] => 28fr2
[title] => loops and things
[link] => https://blah
)
Sandbox
How it works, The main trick here is array fill keys, and array merge. By using these we can create a "template" array. Because merging 2 arrays with the same keys merge in the order of the first array. So we can setup that first array to be the order of $product
and then when we merge into that the "fake" values are replaced with the real values and the order is preserved.
If you wanted to you could also use the result of the array flip (or array fill keys), but then it would be 2 lines of code... :)
And of course we have to use something like array flip or array fill keys to change the values of $product
into the keys we can use for array intersect key.
I used both array fill keys and array flip for variety, in this situation they are somewhat interchangeable. For example this is a bit more efficient:
$map = array_fill_keys($product, null);
$res = array_merge($map,array_intersect_key($data, $map));
print_r($res);
Sandbox
But then it takes 2 lines... I should mention array fill keys is preferred to array flip. It doesn't really matter because the array intersect key filters anything out not in map. But it's "in general" better because then the values of the map array are the same, whereas when using flip they are the numeric keys which can be a bit harder to work with for some situations (but not this one).
I almost for got you can functionize it like this
function ordered_array_intersect_key(array $data, array $map){
return array_merge(($map = array_fill_keys($map, null)),array_intersect_key($data, $map));
}
I took the liberty of naming it something sensible and by using assignment inline in array_merge
you can have your cake and eat it too (reuse array_fill_keys and have 1 line). Something I just happened to think of when making a function out of it.
Sanbox
Enjoy!
UPDATE
Thanks to mosh442, for the idea. You can also use array_walk
to build a new array like this:
$data = [
'title' => 'loops and things',
'id' => '28fr2',
'link' => 'https://blah',
'itemid' => '28fr3',
'quantity' => 3,
//...
];
$product = [
'id',
'title',
'link'
];
$new = [];
array_walk($product, function($v,$k,$data) use (&$new){$new[$v] = $data[$v];},$data);
print_r($new);
Output
Array
(
[id] => 28fr2
[title] => loops and things
[link] => https://blah
)
Sandox
I love questions like this, so much fun....
Filter array of objects on key from array of values JavaScript
Use map()
to loop over the array of objects and create a new array with the result of filtering the object properties.
You should be using FilterArray.includes()
, not key.includes()
.
const finalArray = [ { "cbsa_cde": "33460", "cbsa_nm": "Minneapolis-St. Paul-Bloomington, MN-WI", "countycode": "27053", "hh_50k_100k_201612": 71, "hh_50k_100k_201706": 86, "hh_50k_100k_201712": 60, "hh_50k_100k_201806": 37, "hh_50k_100k_201812": 49, "hh_50k_100k_201906": 35, "hh_50k_100k_201912": 38, "hh_50k_100k_202006": 46, "hh_50k_100k_202012": 58, "hh_100k_250k_201612": 120, "hh_100k_250k_201706": 121, "hh_100k_250k_201712": 153, "hh_100k_250k_201806": 126, "hh_100k_250k_201812": 126, "hh_100k_250k_201906": 125, "hh_100k_250k_201912": 120, "hh_100k_250k_202006": 99, "hh_100k_250k_202012": 84}, { "cbsa_cde": "33460", "cbsa_nm": "Minneapolis-St. Paul-Bloomington, MN-WI", "countycode": "27053","hh_50k_100k_201612": 20, "hh_50k_100k_201706": 33, "hh_50k_100k_201712": 22, "hh_50k_100k_201806": 41, "hh_50k_100k_201812": 52, "hh_50k_100k_201906": 45, "hh_50k_100k_201912": 40, "hh_50k_100k_202006": 41, "hh_50k_100k_202012": 50, "hh_100k_250k_201612": 99, "hh_100k_250k_201706": 108, "hh_100k_250k_201712": 130, "hh_100k_250k_201806": 84, "hh_100k_250k_201812": 90, "hh_100k_250k_201906": 97, "hh_100k_250k_201912": 89, "hh_100k_250k_202006": 95, "hh_100k_250k_202012": 87} ],
filterArray = [ "HH_50K_100K_201612", "HH_50K_100K_201706", "HH_100K_250K_201612", "HH_100K_250K_201706" ];
const result = finalArray.map(jsonData =>
Object.fromEntries(Object.entries(jsonData).filter(([key, value]) => filterArray.includes(key.toUpperCase()))));
console.log(result);
JavaScript How to filter array of objects by dynamic key?
Already Data
[
{item1: { key: 'sdfd', value:'sdfd' }},
{item2: { key: 'sdfd', value:'sdfd' }},
{item3: { key: 'sdfd', value:'sdfd' }}
]
Want Data
Want the data from target
, when target is item1
:
[
{item1: { key: 'sdfd', value:'sdfd' }}
]
Current Code
let arr = [
{item1: { key: 'sdfd', value:'sdfd' }},
{item2: { key: 'sdfd', value:'sdfd' }},
{item3: { key: 'sdfd', value:'sdfd' }}
]
let target = 'item1'
// result array
let want = [
{item1: { key: 'sdfd', value:'sdfd' }},
]
Filtered object search using allowed keys and also a search value
const handleSearch = (searchValue) => {
if (searchValue !== '') {
const allowed = ['name', 'title'];
const list = props.search.list;
const filtered = list
.filter(obj =>
Object.keys(obj)
.some(k => allowed.includes(k))
)
.filter(obj =>
Object.values(obj)
.map(v => v.toLocaleLowerCase())
.some(v => v.includes(searchValue.toLowerCase()))
)
props.search.onChange(filtered)
} else {
props.search.onChange(props.search.list)
}
}
Example
Let's assume props
as:
const props = {
search: {
list: [
{ name: "John", title: 'Owner' },
{ name: "Jane", title: 'Admin' },
{ name: "Reza", title: 'Owner' }
],
onChange: x => console.log(x)
},
}
handleSearch("own")
// [ { name: 'John', title: 'Owner' }, { name: 'Reza', title: 'Owner' } ]
handleSearch("jane")
// [ { name: 'Jane', title: 'Admin' } ]
handleSearch("something")
// []
how to filter a array of object by another object as key in JS?
You could map each key from filters
and filter allData
based on if filterTerm
includes the item being searched, ignoring the filter if filterTerm
is empty. Below example would also allow you to add more items to filterTerm
if needed.
let allData = [
{title:"Adams",age:24,gender:"male"},
{title:"Baker",age:24,gender:"female"},
{title:"Clark",age:23,gender:"male"},
{title:"Davis",age:23,gender:"female"},
{title:"Ghosh",age:23,gender:"female"},
{title:"Adams",age:23,gender:"male"},
{title:"Irwin",age:25,gender:"male"}
]
let filters = {
title:{filterTerm:[]},
gender:{filterTerm:["male"]},
age:{filterTerm:[23]},
}
const getFilterRows = (rows, filters) => {
return rows.filter(row => (
Object.keys(filters)
.map(key => filters[key].filterTerm.length ? filters[key].filterTerm.includes(row[key]) : true)
.every(Boolean))
)
}
let filtered = getFilterRows(allData,filters)
console.log(filtered)
filter array of objects based on separate object keys, values
You could filter as follows:
const FIRST_ARRAY = [ { name: 'Simon', age: 32, occupation: 'Student' }, { name: 'Vera', age: 22, occupation: 'Developer' }];
const FILTERS = { name: 'Simon', age: 32, occupation: ''};
const filtered = FIRST_ARRAY.filter(person => Object.entries(FILTERS) .every(([key, val]) => val !== '' ? person[key] === val : true)); console.log(filtered);
Related Topics
How to Get a Substring Between Two Strings in PHP
How to Get a File Name from a Full Path With PHP
Should I Manually Check For Errors When Calling "MySQLi_Stmt_Prepare"
Is There a Code Obfuscator For PHP
PHP Elvis Operator VS Null Coalescing Operator
Recursive Function to Generate Multidimensional Array from Database Result
Gcm With PHP (Google Cloud Messaging)
MySQL and PHP: Utf-8 With Cyrillic Characters
PHP: How to Send Http Response Code
How to Close a Connection Early
PHP Sessions Across Sub Domains
Strtotime() Doesn't Work With Dd/Mm/Yyyy Format
Multiple Returns from a Function
What Does the Variable $This Mean in PHP
Error Message "Strict Standards: Only Variables Should Be Passed by Reference"
PHP: Return All Dates Between Two Dates in an Array
Delimiter Must Not Be Alphanumeric or Backslash and Preg_Match