从数组的数组中过滤数据的优雅方式
elegant way of filtering data from array of array
如何从array of array中过滤数据?
请在下面给出的示例中找到解释。
我们必须在数据查询中使用startnumber
和endnumber
。
const data = [
{
"name": "x",
"points": [
[100, 50, 1], //[number, value, bit]
[150, 51, 0],
[170, 52, 1],
[200, 53, 0]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1]
]
},
{
"name": "z",
"points": [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1]
]
}
]
// want to find the records with name equal to x & y and number between 100 to 170
const names = ["x", "y"];
const startnumber = 100;
const endnumber = 170;
const finalResult= [];
for(const n of names){
console.log('name', n);
console.log('startnumber', startnumber)
console.log('endnuumber', endnumber)
const result = data.find(x=>x.name === n)
// how to use startnumber and endnumber here in above line/query ? OR some other elegant solution is required
if(result){
finalResult.push('result', result);
}
}
if(finalResult.length){
console.log(finalResult);
}
预期结果应该是
[
{
"name": "x",
"points": [
[100, 50, 1],
[150, 51, 0],
[170, 52, 1],
]
},
{
"name": "y",
"points": [
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
]
}
]
const results = data.filter(elem => !!names.find(name => name == elem.name))
解释:
data.filter
将回调应用于数组的每个元素 data
names.find
将回调应用于数组 names
的每个元素以找到匹配项。
使用 !!
是因为 find
return 是一个元素,所以 !!
会导致双重否定,将其变成布尔值,即预期的 return 来自 find
回调(实际上并非绝对必要,因为 find
returning undefined
将被强制为 false),但它阐明了意图。
- 结果只有
data
的元素具有与 names
中的值匹配的名称属性。
const data = [
{
"name": "x",
"points": [
[100, 50, 1], //[number, value, bit]
[150, 51, 0],
[170, 52, 1],
[200, 53, 0]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[200, 53, 1]
]
},
{
"name": "z",
"points": [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1]
]
}
]
// want to find the records with name equal to x & y and number between 100 to 170
const names = ["x", "y"];
const startNumber = 100;
const endNumber = 170;
const results = data
.filter(elem => !!names.find(name => name == elem.name))
.map(elem => {
return {
name: elem.name,
points: elem.points.filter(point => point[0] >= startNumber && point[0] <= endNumber)
}
})
.filter(elem => elem.points.length > 0)
console.log(results)
该任务和两个给定的数据结构意味着每个数据项的双重过滤过程。
- 通过名称识别数据项(来自额外提供的
names
数组)。
- 根据
points
项的第一个数组项(number
值)是否在某个数字范围内(由额外提供的定义)来过滤每个数据项的 points
数组startnumber
和 endnumber
值)。
因此,一个可行的方法是 reduce
提供的 data
数组由一个缩减器函数处理,每个 data
项目负责上述两个任务。
reducer 函数的 initial value 将是一种配置 and/or 收集器对象,具有...
name
查找(作为 Map
实例应用)以显式处理 data
项。
startnumber
和endnumber
范围值分别为lowerNumber
upperNumber
。
- 和一个
result
数组,其中只有那些 data
项被推入其中满足所有要求。
function collectItemsByNameWhichHavePointsInNumberRange(collector, item) {
const { nameLookup, lowerNumber, upperNumber, result } = collector;
let { name, points } = item;
// ... collect items by name ...
if (nameLookup.has(name)) {
points = points
.filter(([number]) =>
(number >= lowerNumber) && (number <= upperNumber)
);
// ... which (actually do) have points (with)in (a) number range.
// (according to the above `points` filter result)
if (points.length >= 1) {
result
.push({
...item,
points,
});
}
}
return collector;
}
const data = [{
name: "x",
points: [
//[number, value, bit]
[100, 50, 1],
[150, 51, 0],
[170, 52, 1],
[200, 53, 0],
],
}, {
name: "y",
points: [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1],
],
}, {
name: "z",
points: [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1],
],
}];
const names = ["x", "y"];
const startnumber = 100;
const endnumber = 170;
const { result } = data
.reduce(collectItemsByNameWhichHavePointsInNumberRange, {
nameLookup: new Map(names.map(value => [value, value])),
lowerNumber: startnumber,
upperNumber: endnumber,
result: [],
});
console.log({ result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
最优雅的解决方案:
const res = data.reduce((acc, curr) => {
const { name, points } = curr
const filteredPoints = points.filter(p => p[0] >= startNumber && p[0] <= endNumber)
return names.includes(name) && filteredPoints.length > 0 ? acc.concat({ name, points: filteredPoints }) : acc
}, [])
如何从array of array中过滤数据?
请在下面给出的示例中找到解释。
我们必须在数据查询中使用startnumber
和endnumber
。
const data = [
{
"name": "x",
"points": [
[100, 50, 1], //[number, value, bit]
[150, 51, 0],
[170, 52, 1],
[200, 53, 0]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1]
]
},
{
"name": "z",
"points": [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1]
]
}
]
// want to find the records with name equal to x & y and number between 100 to 170
const names = ["x", "y"];
const startnumber = 100;
const endnumber = 170;
const finalResult= [];
for(const n of names){
console.log('name', n);
console.log('startnumber', startnumber)
console.log('endnuumber', endnumber)
const result = data.find(x=>x.name === n)
// how to use startnumber and endnumber here in above line/query ? OR some other elegant solution is required
if(result){
finalResult.push('result', result);
}
}
if(finalResult.length){
console.log(finalResult);
}
预期结果应该是
[
{
"name": "x",
"points": [
[100, 50, 1],
[150, 51, 0],
[170, 52, 1],
]
},
{
"name": "y",
"points": [
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
]
}
]
const results = data.filter(elem => !!names.find(name => name == elem.name))
解释:
data.filter
将回调应用于数组的每个元素data
names.find
将回调应用于数组names
的每个元素以找到匹配项。
使用 !!
是因为find
return 是一个元素,所以!!
会导致双重否定,将其变成布尔值,即预期的 return 来自find
回调(实际上并非绝对必要,因为find
returningundefined
将被强制为 false),但它阐明了意图。- 结果只有
data
的元素具有与names
中的值匹配的名称属性。
const data = [
{
"name": "x",
"points": [
[100, 50, 1], //[number, value, bit]
[150, 51, 0],
[170, 52, 1],
[200, 53, 0]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[200, 53, 1]
]
},
{
"name": "z",
"points": [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1]
]
}
]
// want to find the records with name equal to x & y and number between 100 to 170
const names = ["x", "y"];
const startNumber = 100;
const endNumber = 170;
const results = data
.filter(elem => !!names.find(name => name == elem.name))
.map(elem => {
return {
name: elem.name,
points: elem.points.filter(point => point[0] >= startNumber && point[0] <= endNumber)
}
})
.filter(elem => elem.points.length > 0)
console.log(results)
该任务和两个给定的数据结构意味着每个数据项的双重过滤过程。
- 通过名称识别数据项(来自额外提供的
names
数组)。 - 根据
points
项的第一个数组项(number
值)是否在某个数字范围内(由额外提供的定义)来过滤每个数据项的points
数组startnumber
和endnumber
值)。
因此,一个可行的方法是 reduce
提供的 data
数组由一个缩减器函数处理,每个 data
项目负责上述两个任务。
reducer 函数的 initial value 将是一种配置 and/or 收集器对象,具有...
name
查找(作为Map
实例应用)以显式处理data
项。startnumber
和endnumber
范围值分别为lowerNumber
upperNumber
。- 和一个
result
数组,其中只有那些data
项被推入其中满足所有要求。
function collectItemsByNameWhichHavePointsInNumberRange(collector, item) {
const { nameLookup, lowerNumber, upperNumber, result } = collector;
let { name, points } = item;
// ... collect items by name ...
if (nameLookup.has(name)) {
points = points
.filter(([number]) =>
(number >= lowerNumber) && (number <= upperNumber)
);
// ... which (actually do) have points (with)in (a) number range.
// (according to the above `points` filter result)
if (points.length >= 1) {
result
.push({
...item,
points,
});
}
}
return collector;
}
const data = [{
name: "x",
points: [
//[number, value, bit]
[100, 50, 1],
[150, 51, 0],
[170, 52, 1],
[200, 53, 0],
],
}, {
name: "y",
points: [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1],
],
}, {
name: "z",
points: [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1],
],
}];
const names = ["x", "y"];
const startnumber = 100;
const endnumber = 170;
const { result } = data
.reduce(collectItemsByNameWhichHavePointsInNumberRange, {
nameLookup: new Map(names.map(value => [value, value])),
lowerNumber: startnumber,
upperNumber: endnumber,
result: [],
});
console.log({ result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
最优雅的解决方案:
const res = data.reduce((acc, curr) => {
const { name, points } = curr
const filteredPoints = points.filter(p => p[0] >= startNumber && p[0] <= endNumber)
return names.includes(name) && filteredPoints.length > 0 ? acc.concat({ name, points: filteredPoints }) : acc
}, [])