javascript - 如何通过多个相同的属性过滤对象数组
问题描述
描述
请注意,entry1和entry4共享和的相同值。property: 'subject'
property: 'field'
问题
我正在寻找一种高效且干净的方法来过滤此数组并获取与这些ies共享两个 value
s的条目。property
更新:
返回值
我不是试图转换数据,而是分析它。因此分析的返回值应如下所示:
[['entry1', 'entry4'],...]
并且通过这个分析列表,我可以轻松地将我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" }
];
解决方案
我必须说输入数据结构不是最优的,并且使用“主题”作为真实对象属性和值将 property
使其更加混乱。我将第一个概念(真正的 subject
)称为“条目”,因为样本值为“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);
推荐阅读
- excel - 在excel中将多个单元格合并到一行中
- python - 据称在使用 super 时存在误解
- c - 读取 volatile 变量有持久效果?米斯拉 C
- opengl - 从帧缓冲区复制整个立方体贴图纹理
- java - 如何在 Intelijj IDEA 中仅格式化更改的行而不是整个文件
- javascript - 如何更改输入字段的值后退焦点
- c - 使用 T(n) 方法计算时间复杂度?
- java - TensorFlow Lite 模型 Android:找不到要标记的轴。要标记的有效轴的大小应大于 1
- sql - BigQuery - 查找过去 365 天内每个值的最新条目
- flutter - 展开一个 ExpansionTile 关闭所有其他的?