描述
请注意 entry1 和 entry4 为 property: 'subject'
和 共享相同的值属性:“字段”
。
问题
我正在寻找一种有效且干净的方法来过滤此数组并获取共享那些属性
的两者值
的条目。
更新:
返回值
我不是要转换数据,而是要对其进行分析。 所以分析的返回值应该是这样的:
[['entry1', 'entry4'],...]
通过这种分析 list,我可以轻松地将我的 triples = [...]
转换为一个 triples 列表,其中我删除了一个条目(无关紧要,可以是'entry1'或'entry4'),并更新另一个
[
{ subject: "entry1", property: "subject", value: "sport" },
{ subject: "entry1", property: "field", value: "category" },
{ subject: "entry1", property: "content", value: "football" },
{ subject: "entry1", property: "content", value: "basketball" },
]
附言
我不是在寻找类似的解决方案:
array.filter(({property, value})=> property === 'sport' && value === 'category')
我不知道“运动”或“类别”。 这些是动态值。
- 我的实际数据要大得多,每个条目 包含更多的属性类型。它也没有我在这里展示的那么好。我确实简化了它,所以请记住性能。
代码片段:
const triples = [
{ subject: "entry1", property: "subject", value: "sport" },
{ subject: "entry1", property: "field", value: "category" },
{ subject: "entry1", property: "content", value: "football" },
{ subject: "entry4", property: "subject", value: "sport" },
{ subject: "entry4", property: "field", value: "category" },
{ subject: "entry4", property: "content", value: "basketball" },
{ subject: "entry2", property: "subject", value: "music" },
{ subject: "entry2", property: "field", value: "category" },
{ subject: "entry2", property: "content", value: "notes" },
{ subject: "entry3", property: "subject", value: "painting" },
{ subject: "entry3", property: "field", value: "category" },
{ subject: "entry3", property: "content", value: "drawings" }
];
最佳答案
我必须说输入数据结构不是最优的,使用“subject”作为一个真实的对象属性和一个值for property
将使它更令人困惑。我将第一个概念(真实 主题
)称为“条目”,因为示例值是“entry1”、“entry2”……
下面是提取示例数据的 ["entry1", "entry4"]
的方法:
根据数据进入对象对数据进行分组,其中“属性”和“值”被转换为键/值对,因此您会得到如下内容:
{ entry1: { subject: "sport", field: "category", content: "football" }, entry4: { subject: "sport", field: "category", content: "basketball" }, entry2: { subject: "music", field: "category", content: "notes" }, entry3: { subject: "painting", field: "category", content: "drawings" } }
这将更容易使用。下面的代码实际上会创建一个
Map
而不是一个普通的对象,但原理是一样的。为这些对象定义一个新的
group
属性,其中值由主题和字段组成,字符串化为 JSON。例如,上述结果的第一个对象将扩展为:group: '["sport","category"]'
创建一个条目映射,以它们的组值作为键。所以这会给出这个结果:
{ '["sport","category"]': ["entry1","entry4"], '["music","category"]': ["entry2"], '["painting","category"]': ["entry3"] }
现在只列出值(子数组)并且只列出具有多个条目值的值是一个简单的步骤。
实现如下:
const triples = [{subject: "entry1", property: "subject", value: "sport"},{subject: "entry1", property: "field", value: "category"},{subject: "entry1", property: "content", value: "football"},{subject: "entry4", property: "subject", value: "sport"},{subject: "entry4", property: "field", value: "category"},{subject: "entry4", property: "content", value: "basketball"},{subject: "entry2", property: "subject", value: "music"},{subject: "entry2", property: "field", value: "category"},{subject: "entry2", property: "content", value: "notes"},{subject: "entry3", property: "subject", value: "painting"},{subject: "entry3", property: "field", value: "category"},{subject: "entry3", property: "content", value: "drawings"},];
// 1. Group the data by subject into objects where "property" and "value" are translated into key/value pairs:
const entries = new Map(triples.map(o => [o.subject, { entry: o.subject }]));
triples.forEach(o => entries.get(o.subject)[o.property] = o.value);
// 2. Define a group value for these objects (composed of subject and field)
entries.forEach(o => o.group = JSON.stringify([o.subject, o.field]));
// 3. Create Map of entries, keyed by their group value
const groups = new Map(Array.from(entries.values(), o => [o.group, []]));
entries.forEach(o => groups.get(o.group).push(o.entry));
// 4. Keep only the subarrays that have more than one value
const result = [...groups.values()].filter(group => group.length > 1);
console.log(result);
请注意,输出是一个嵌套数组,因为理论上可以有更多组合条目,例如 [ ["entry1", "entry4"], ["entry123", "entry521", "entry951"] ]
可以修改/扩展以上以获得最终过滤结果。在第三步中,您仍然会收集对象(而不仅仅是条目值),然后将过滤后的结果映射回原始格式:
const triples = [{subject: "entry1", property: "subject", value: "sport"},{subject: "entry1", property: "field", value: "category"},{subject: "entry1", property: "content", value: "football"},{subject: "entry4", property: "subject", value: "sport"},{subject: "entry4", property: "field", value: "category"},{subject: "entry4", property: "content", value: "basketball"},{subject: "entry2", property: "subject", value: "music"},{subject: "entry2", property: "field", value: "category"},{subject: "entry2", property: "content", value: "notes"},{subject: "entry3", property: "subject", value: "painting"},{subject: "entry3", property: "field", value: "category"},{subject: "entry3", property: "content", value: "drawings"},];
// 1. Group the data by subject into objects where "property" and "value" are translated into key/value pairs:
const entries = new Map(triples.map(o => [o.subject, { entry: o.subject }]));
triples.forEach(o => entries.get(o.subject)[o.property] = o.value);
// 2. Define a group value for these objects (composed of subject and field)
entries.forEach(o => o.group = JSON.stringify([o.subject, o.field]));
// 3. Create Map of objects(*), keyed by their group value
const groups = new Map(Array.from(entries.values(), o => [o.group, []]));
entries.forEach(o => groups.get(o.group).push(o));
// 4. Keep only the subarrays that have more than one value
const result = [...groups.values()].filter(group => group.length > 1)
// 5. ...and convert it back to the original format:
.flatMap(group => [
{ subject: group[0].entry, property: "subject", value: group[0].subject },
{ subject: group[0].entry, property: "field", value: group[0].field },
...group.map(o => ({ subject: group[0].entry, property: "content", value: o.content }))
]);
console.log(result);
关于javascript - 如何通过多个相同的属性过滤对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54483300/