[英]JavaScript - Filter Object from criteria array, by deeply nested object key?
I have been breaking my head the last few days trying to implement the following functionality:过去几天我一直在努力实现以下功能:
I have an incoming object, with a nested sub-object that's a list of dates.我有一个传入的 object,它有一个嵌套的子对象,它是一个日期列表。 I would like to filter the original object against a range of dates, and return the modified filtered object, with only the specified dates.
我想根据一系列日期过滤原始 object,并返回修改后的过滤 object,仅包含指定的日期。
Here is the desired functionality:这是所需的功能:
let incomingObject = {
'one': {
id: "one",
dates: {
"2021-05-01": [{ a: "foo", b: "bar" }],
"2021-05-02": [{ a: "foo", b: "bar" }] } },
'two': {
id: "two",
dates: {
"2021-05-01": [{ a: "foo", b: "bar" }, { a: "foo2", b: "bar2" }],
"2021-05-02": [{ a: "baz", b: "far" }] } },
'three': {
id: "three",
dates: {
"2021-05-03": [{ a: "foo", b: "bar" }],
"2021-05-02": [{ a: "foo", b: "bar" }] } } };
// Function to get an array between two dates
const getDaysArray = function (s, e) {
for (var a = [], d = new Date(s); d <= new Date(e); d.setDate(d.getDate() + 1)) {
a.push(new Date(d));
}
let aStrings = a.map((date) => date.toISOString().slice(0, 10));
return aStrings;
};
I have no idea how to implement this function, that would return the "filtered" object:我不知道如何实现这个 function,它将返回“过滤”的 object:
filterResults(incomingObject, getDaysArray("2021-05-01", "2021-05-01"));
This is the desired result - all the (sub-)objects that don't pass the filter, are left out:这是期望的结果 - 所有未通过过滤器的(子)对象都被排除在外:
let desiredResult = {
'one': {
id: "one",
dates: {
"2021-05-01": [{ a: "foo", b: "bar" }] } },
'two': {
id: "two",
dates: {
"2021-05-01": [{ a: "foo", b: "bar" }, { a: "foo2", b: "bar2" }] } } };
And my progress so far:到目前为止我的进展:
let dateRange = getDaysArray("2021-05-01", "2021-05-01");
// This logs out only the required keys –– however, logging out the whole "parent" object is completely beyond my comprehension at the moment...
const filteredImages = Object.keys(images).forEach((key) => {
let imgObject = images[key];
Object.keys(images[key].dates).forEach((key) => {
if (dateRange.includes(key)) {
console.log(key);
}
});
});
All help or pointers much appreciated!非常感谢所有帮助或指示!
const incomingObject={one:{id:"one",dates:{"2021-05-01":[{a:"foo",b:"bar"}],"2021-05-02":[{a:"foo",b:"bar"}]}},two:{id:"two",dates:{"2021-05-01":[{a:"foo",b:"bar"},{a:"foo2",b:"bar2"}],"2021-05-02":[{a:"baz",b:"far"}]}},three:{id:"three",dates:{"2021-05-03":[{a:"foo",b:"bar"}],"2021-05-02":[{a:"foo",b:"bar"}]}}}; const getDaysArray = function(e,t){for(var a=[],n=new Date(e);n<=new Date(t);n.setDate(n.getDate()+1))a.push(new Date(n));return a.map(e=>e.toISOString().slice(0,10))} const filterResults = (data, days) => Object.entries(data).reduce((result, [k, v]) => { const {dates, ...rest} = v const filteredDates = days.reduce((acc, date) => { if(v.dates[date]) acc[date] = v.dates[date] return acc }, {}) if (Object.keys(filteredDates).length) result.push([k, {...rest, dates: filteredDates }]) return result }, []) const res = filterResults( incomingObject, getDaysArray("2021-05-01", "2021-05-01") ) console.log(Object.fromEntries(res))
.as-console-wrapper { max-height: 100%;important: top; 0; }
What about this one?这个如何? I find it very concise and modern:
我觉得它非常简洁和现代:
const filterResults = (data, days) =>
Object.entries(data).reduce((acc, [n, { id, dates }]) => {
const ds = Object.entries(dates).filter(([d,]) => days.includes(d))
return ds.length ? { ...acc, [n]: { id, dates: Object.fromEntries(ds) } } : acc
}, {})
The nice thing here is to use nested destructuring patterns and spread operator to avoid boilerplate code.这里的好处是使用嵌套解构模式和扩展运算符来避免样板代码。
Also, while doing reduce
over Object.entries
, we can construct an object directly, without need of an intermediary array.此外,在对
Object.entries
进行reduce
的同时,我们可以直接构造一个 object,而无需中间数组。 In this implementation, everything is done in just one iteration over the original data
array, so it performs better.在这个实现中,一切都在原始
data
数组的一次迭代中完成,因此它的性能更好。
Additional information on the techniques used in the snippet:有关片段中使用的技术的其他信息:
Lambda syntax for anonymous function (arrow function =>
) ; 匿名 function 的 Lambda 语法(箭头 function
=>
) ;
const filterResults = (data, days) =>
Array.reduce()
, using empty object {}
as initial accumulator ; Array.reduce()
,使用空的 object {}
作为初始累加器;
Array and Object nested argument destructuring [a, { b, c }]
; 数组和 Object 嵌套参数解构
[a, { b, c }]
;
Object.entries(data).reduce((acc, [n, { id, dates }]) => {
Ignoring some values with Array destructuring [d,]
; 使用 Array destructuring
[d,]
忽略一些值;
const ds = Object.entries(dates).filter(([d,]) => days.includes(d))
Spread operator for object literals {...acc }
; object 文字的扩展运算符
{...acc }
;
Object.fromEntries
function : Object.fromEntries
function :
return ds.length? {...acc, [n]: { id, dates: Object.fromEntries(ds) } }: acc
You can use the array methods filter()
您可以使用数组方法
filter()
In your case it could look something like this:在您的情况下,它可能看起来像这样:
const incoming = [ { nested: { date: '2021-05-01' } }, { nested: { date: '2021-03-16' } }, { nested: { date: '2021-02-05' } }, { nested: { date: '2021-01-20' } }, ] let someRange = ['2021-02-05', '2021-03-24'] const result = incoming.filter((item) => { return item.nested.date >= someRange[0] && item.nested.date <= someRange[1] }) console.log(result)
You need to transform your object into an array with Object.values(yourArray)
to use the filter()
method.您需要使用
filter()
方法将 object 转换为具有Object.values(yourArray)
的数组。
EDIT:编辑:
Just read your post again.再看一遍你的帖子。 You can use the
Object.keys()
to retrieve the keys from your object like so:您可以使用
Object.keys()
从 object 中检索密钥,如下所示:
const dates = { "2021-05-01": [{ a: "foo", b: "bar", }, { a: "foo2", b: "bar2", }, ], "2021-05-02": [{ a: "baz", b: "far", }, ], } const dateKeys = Object.keys(dates) console.log(`Keys from date object: ${dateKeys}`) const result = dateKeys.filter((item) => { return item >= '2021-05-02' }) console.log(result)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.