Я пытаюсь сгруппировать связанные объекты JavaScript в массиве по ключу.

Но я застрял на месте.

У меня есть массив объектов JavaScript что-то вроде этого:

[
    {
        "text": "hello world",
        "startPos": 0,
        "endPos": 12,
        "value": "hello world",
        "entity": "Greeting"
    },
    {
        "text": "hello world",
        "startPos": 0,
        "endPos": 6,
        "value": "hello",
        "entity": "Greeting"
    }
]

Я сделал следующий код, но я застрял.

a = [
  {
    "text": "hello world",
    "startPos": 0,
    "endPos": 12,
    "value": "hello world",
    "entity": "Greeting"
  },
  {
    "text": "hello world",
    "startPos": 0,
    "endPos": 6,
    "value": "hello",
    "entity": "Greeting"
  }
]

let result = a.reduce((acc, d) => {
  const found = acc.find(a => a.text == d.text);
  const entitiesArray = {
    startPos: d.startPos,
    endPos: d.endPos,
    entity: d.entity
  };
  if (found) {
    found.entities.push(entitiesArray);
  } else {
    acc.push({});
  }
  return acc;
}, []);

console.log(JSON.stringify(result, undefined, 4));

Объект JavaScript повторяется на основе ключа "text". Я хочу сгруппировать вышеуказанный массив в один объект на основе ключа "text".

Что-то вроде этого:

[
    {
        "text": "hello world",
        "entities": [
                {
                    "startPos": 0,
                    "endPos": 12,
                    "value": "hello world",
                    "entity": "Greeting"
                },
                {
                    "startPos": 0,
                    "endPos": 6,
                    "value": "hello",
                    "entity": "Greeting"
                }
        ]
    }
]
0
Kunal Mukherjee 26 Фев 2018 в 12:42

3 ответа

Лучший ответ

Вы пропустили добавление объекта с text в массив, когда found имеет значение false. Так что в следующих итерациях он не сможет найти объект, сравнивающий их тексты

Также, если ваша IDE и Engine поддерживают новое предложение ES, вы можете использовать Rest / Spread Свойства

const a = [
  {
    "text": "hello world",
    "startPos": 0,
    "endPos": 12,
    "value": "hello world",
    "entity": "Greeting"
  },
  {
    "text": "hello world",
    "startPos": 0,
    "endPos": 6,
    "value": "hello",
    "entity": "Greeting"
  }
]

let result = a.reduce((acc, d) => {
  const found = acc.find(a => a.text == d.text);
  
  const { text, ...entitiesArray } = { ...d }; // <- Rest/Spread properties
  
  found ? found.entities.push(entitiesArray) 
        : acc.push({ text: d.text, entities: [entitiesArray]})

  return acc;
}, []);

console.log(result);
2
Suren Srapyan 26 Фев 2018 в 09:53

Вы также можете сделать более короткую версию, используя reduce и Object.values

let a = [{
    "text": "hello world",
    "startPos": 0,
    "endPos": 12,
    "value": "hello world",
    "entity": "Greeting"
  },
  {
    "text": "hello world",
    "startPos": 0,
    "endPos": 6,
    "value": "hello",
    "entity": "Greeting"
  }
];

let result = Object.values(a.reduce((c, v) => {
  c[v.text] = c[v.text] || {text: v.text,entities: []};
  c[v.text].entities.push(v);
  return c;
}, {}));

console.log(result);

Без свойства text

let a = [{
    "text": "hello world",
    "startPos": 0,
    "endPos": 12,
    "value": "hello world",
    "entity": "Greeting"
  },
  {
    "text": "hello world",
    "startPos": 0,
    "endPos": 6,
    "value": "hello",
    "entity": "Greeting"
  }
];

let result = Object.values(a.reduce((c, v) => {
  let {text: _,...o} = v;
  c[v.text] = c[v.text] || {text: v.text,entities: []};
  c[v.text].entities.push(o);
  return c;
}, {}));

console.log(result);
2
Eddie 26 Фев 2018 в 10:10

Вы можете добавить новый объект с текстом и массив для объектов.

Это решение берет разрушенный объект и строит новые объекты с ключами.

var a = [{ text: "hello world", startPos: 0, endPos: 12, value: "hello world", entity: "Greeting" }, { text: "hello world", startPos: 0, endPos: 6, value: "hello", entity: "Greeting" }],
    result = a.reduce((acc, { text, startPos, endPos, entity, value }) => {
        var found = acc.find(a => a.text === text),
            subEntity = { startPos, endPos, entity, value };

        if (found) {
            found.entities.push(subEntity);
        } else {
            acc.push({ text, entities: [subEntity] });
        }
        return acc;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

С остальными параметрами ... для разрушения свойств и BABEL.

var a = [{ text: "hello world", startPos: 0, endPos: 12, value: "hello world", entity: "Greeting" }, { text: "hello world", startPos: 0, endPos: 6, value: "hello", entity: "Greeting" }],
    result = a.reduce((acc, { text, ...subEntity }) => {
        var found = acc.find(a => a.text === text);

        if (found) {
            found.entities.push(subEntity);
        } else {
            acc.push({ text, entities: [subEntity] });
        }
        return acc;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0
Nina Scholz 26 Фев 2018 в 10:12