如何根据 属性 对 javascript 数组进行分组?
How to group javascript array based on some property?
我有一个 JS 对象数组,如下所示:
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
行在整个 myArray 中是唯一的,每行都有一些文本(不是唯一的)。
如何将每个文本与其对应的行匹配?
最后的结果应该是这样的:
var myNewArray = [
{ text: 31, line: [20] },
{ text: 80, line: [20, 10] },
{ text: 22, line: [10] }
]
可能最简单的方法是首先构建一个按文本索引行的中间 Map
:
const data = [
{line: 20, text: [31,80]},
{line: 10, text: [80,22]}
];
const result = [...data.reduce((map, {line, text}) => {
text.forEach(t => {
map.has(t) || map.set(t, []);
map.get(t).push(line);
});
return map;
}, new Map()).entries()].map(([text, line]) => ({text, line}));
console.log(result);
一些方法 Map
。
因此您会得到一张临时地图,其中收集了所有 text
,按 line
分组。要获取对象数组,请将 key/values 对映射为预定义的属性。
因为有嵌套的数据数组,你需要对数据进行归一化以获得单个 line
/text
值,然后按 [=13 添加分组=],
const
data = [{ line: 20, text: [31, 80] }, { line: 10, text: [80, 22] }],
result = Array.from(
data
.flatMap(({ line, text }) => text.map(text => ({ text, line })))
.reduce((m, { text, line }) => m.set(text, [...(m.get(text) || []), line]), new Map),
([text, line]) => ({ text, line })
);
console.log(result);
或者一步完成,但使用减少外部数组(line
)和内部数组(text
数组)的嵌套方法。
const
data = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
],
result = Array.from(
data.reduce(
(m, { line, text }) =>
text.reduce(
(n, text) => n.set(text, [...(n.get(text) || []), line]),
m
),
new Map
),
([text, line]) => ({ text, line })
);
console.log(result);
这里有一个简单的解决方案。
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
var myNewArray = []
myArray.forEach((item) => {
item.text.forEach((t) => {
const index = myNewArray.findIndex((e => e.text === t))
index === -1
? myNewArray.push({text: t, line: [item.line]})
: myNewArray[index].line.push(item.line)
})
})
console.log(myNewArray)
方法如下:
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
var newArray = myArray.reduce((acc, {line, text}) => {
for( let t of text ){
const match = acc.find(({text}) => text == t) // check if the text already exists in newArray
if( match ) match.lines.push(line) // if exists, add the line to that text
else acc.push({text:t, lines:[line]}) // it not, create a new object with that line
}
return acc
}, [])
console.log( newArray )
或者首先生成一个对象而不是一个数组,如果你的数据集巨大更快 =31=],然后在最后将其转换为数组:
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
// generate a key/value pairs for text/lines
var newArray = myArray.reduce((acc, {line, text}) => {
for( let t of text )
acc[t] = [...(acc[t] || []), line]
return acc
}, {})
// convert the above Object to an Array of Objects (AKA Collection)
newArray = Object.entries(newArray).map(([text,lines]) => ({text, lines}))
console.log( newArray )
我有一个 JS 对象数组,如下所示:
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
行在整个 myArray 中是唯一的,每行都有一些文本(不是唯一的)。 如何将每个文本与其对应的行匹配?
最后的结果应该是这样的:
var myNewArray = [
{ text: 31, line: [20] },
{ text: 80, line: [20, 10] },
{ text: 22, line: [10] }
]
可能最简单的方法是首先构建一个按文本索引行的中间 Map
:
const data = [
{line: 20, text: [31,80]},
{line: 10, text: [80,22]}
];
const result = [...data.reduce((map, {line, text}) => {
text.forEach(t => {
map.has(t) || map.set(t, []);
map.get(t).push(line);
});
return map;
}, new Map()).entries()].map(([text, line]) => ({text, line}));
console.log(result);
一些方法 Map
。
因此您会得到一张临时地图,其中收集了所有 text
,按 line
分组。要获取对象数组,请将 key/values 对映射为预定义的属性。
因为有嵌套的数据数组,你需要对数据进行归一化以获得单个
line
/text
值,然后按 [=13 添加分组=],const data = [{ line: 20, text: [31, 80] }, { line: 10, text: [80, 22] }], result = Array.from( data .flatMap(({ line, text }) => text.map(text => ({ text, line }))) .reduce((m, { text, line }) => m.set(text, [...(m.get(text) || []), line]), new Map), ([text, line]) => ({ text, line }) ); console.log(result);
或者一步完成,但使用减少外部数组(
line
)和内部数组(text
数组)的嵌套方法。const data = [ { line: 20, text: [31, 80] }, { line: 10, text: [80, 22] } ], result = Array.from( data.reduce( (m, { line, text }) => text.reduce( (n, text) => n.set(text, [...(n.get(text) || []), line]), m ), new Map ), ([text, line]) => ({ text, line }) ); console.log(result);
这里有一个简单的解决方案。
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
var myNewArray = []
myArray.forEach((item) => {
item.text.forEach((t) => {
const index = myNewArray.findIndex((e => e.text === t))
index === -1
? myNewArray.push({text: t, line: [item.line]})
: myNewArray[index].line.push(item.line)
})
})
console.log(myNewArray)
方法如下:
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
var newArray = myArray.reduce((acc, {line, text}) => {
for( let t of text ){
const match = acc.find(({text}) => text == t) // check if the text already exists in newArray
if( match ) match.lines.push(line) // if exists, add the line to that text
else acc.push({text:t, lines:[line]}) // it not, create a new object with that line
}
return acc
}, [])
console.log( newArray )
或者首先生成一个对象而不是一个数组,如果你的数据集巨大更快 =31=],然后在最后将其转换为数组:
var myArray = [
{ line: 20, text: [31, 80] },
{ line: 10, text: [80, 22] }
]
// generate a key/value pairs for text/lines
var newArray = myArray.reduce((acc, {line, text}) => {
for( let t of text )
acc[t] = [...(acc[t] || []), line]
return acc
}, {})
// convert the above Object to an Array of Objects (AKA Collection)
newArray = Object.entries(newArray).map(([text,lines]) => ({text, lines}))
console.log( newArray )