【问题标题】:Not able to reduce related JavaScript objects in an array无法减少数组中的相关 JavaScript 对象
【发布时间】:2018-02-26 09:42:32
【问题描述】:

我正在尝试将相关的 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"
                }
        ]
    }
]

【问题讨论】:

  • 您希望"text": "hello world" 在第二个对象中吗?还是复制粘贴问题
  • 为什么第一个实体没有text,而第二个实体没有entity
  • 不,我得到两个“不同”的对象,它们的 text 键相同,我想将它们分组。
  • 但是您在实体上拥有的对象(所需的输出)与您开始的不同
  • @Eddie 更新了问题。

标签: javascript json ecmascript-6


【解决方案1】:

found 为假时,您错过了将带有text 的对象添加到数组中。所以在接下来的迭代中,它无法找到比较它们的文本的对象

另外,如果你的 IDE 和引擎支持新的 ES 提案,你可以使用Rest/Spread Properties

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);

【讨论】:

  • const entitiesArray = Object.assign({}, d); 它复制了整个对象,它也有 text 键,我只想要选定的属性,如问题中所述。
  • 您的输入数据与 OP 输入数据不匹配。
  • const { text, ...entitiesArray } = { ...d }; // &lt;- Rest/Spread properties 这行是做什么的?
  • 我在其中添加了链接,您可以在其中阅读更多内容。简而言之,它获取属性text并将其分配给左侧的text变量,其余属性只是复制到entitiesArray
【解决方案2】:

您还可以使用reduceObject.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);

【讨论】:

    【解决方案3】:

    您可以为实体添加一个带有文本的新对象和一个数组。

    此解决方案采用已破坏的对象并使用键构建新对象。

    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; }

    rest parameters ... 用于destructuring 属性和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; }

    【讨论】:

    • 所以我必须在这里提到对象的所有键a.reduce((acc, { text, startPos, endPos, entity, value }) =&gt; {以及累加器?
    • 其实是的,因为其余的语法并不适用于所有浏览器。
    • 其余参数在支持ES6的浏览器中是否支持?
    • 对象不支持。在功能上,是支持的。
    猜你喜欢
    • 2018-09-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 2021-10-18
    • 2021-04-02
    • 2020-12-30
    • 2019-03-26
    相关资源
    最近更新 更多