Я должен сказать, что структура входных данных не оптимальна, и использование «субъекта» как свойства реального объекта и как значения для property
сделает его еще более запутанным.Я назову первое понятие ( real subject
) «entry», поскольку значениями примеров являются «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);