首页 > 解决方案 > 如何根据键组合对象数组中的特定项目:每个对象的值同时保持顺序?

问题描述

我有一个对象数组,如下所示。每个对象都有永久键“类型”,并根据“类型”添加新键。

因此,如果type: 'text',我们有一个新的键“文本”。

如果type: 'notText',我们有一个新的键'attrs'。

arrayOfObj = [
    {
        "type": "text",
        "text": "="
    },
    {
        "type": "text",
        "text": " "
    },
    {
        "type": "text",
        "text": "S"
    },
    {
        "type": "text",
        "text": "O"
    },
    {
        "type": "notText",
        "attrs": {
            "id": 20,
            "data": "Something",
        }
    },
    {
        "type": "text",
        "text": "H"
    },
    {
        "type": "text",
        "text": "E"
    },
    {
        "type": "text",
        "text": "Y"
    },
    {
        "type": "notText",
        "attrs": {
            "id": 20,
            "data": "Other",
        }
    },
    {
        "type": "text",
        "text": "="
    },
    {
        "type": "text",
        "text": "T"
    },
    {
        "type": "text",
        "text": "O"
    },
]

对象是有序的,因此取决于每个项目的“类型”和顺序,然后我需要像这样组合它们:

arrayOfObj = [
    {
        "type": "text",
        "text": "= SO"
    },
    {
        "type": "notText",
        "attrs": {
            "id": 20,
            "data": "Something",
        }
    }
    {
        "type": "text",
        "text": "HEY"
    },
    {
        "type": "notText",
        "attrs": {
            "id": 20,
            "data": "Other",
        }
    },
    {
        "type": "text",
        "text": "=TO"
    },
]

总之,只要 'type' = 'text' 然后将每个对象与类型 'text' 组合在一起。如果下一个对象的类型为 'notText',则不要理会它,直到下一个具有 'type' = 'text' 的项目。然后结合这些。

我已经用工作答案问过一个与此类似的问题

let arrayOfObj = [{
    "type": "text",
    "text": "="
  },
  {
    "type": "text",
    "text": " "
  },
  {
    "type": "text",
    "text": "S"
  },
  {
    "type": "text",
    "text": "O"
  },
  {
    "type": "notText",
    "attrs": {
      "id": 20,
      "data": "Something",
    }
  },
  {
    "type": "text",
    "text": "H"
  },
  {
    "type": "text",
    "text": "E"
  },
  {
    "type": "text",
    "text": "Y"
  },
  {
    "type": "notText",
    "attrs": {
      "id": 20,
      "data": "Other",
    }
  },
  {
    "type": "text",
    "text": "="
  },
  {
    "type": "text",
    "text": "T"
  },
  {
    "type": "text",
    "text": "O"
  },
];
let newThing = arrayOfObj.reduce(
  (textKey, typeKey) => {
    if (typeKey.type === "text") {
      textKey[0].text += typeKey.text;
    } else {
      textKey.push({
        type: typeKey.type,
        attrs: typeKey.attrs
      });
    }
    return textKey;
  }, [{
    type: "text",
    text: ""
  }]
);
console.log(newThing);

但是,它结合了“type”=“text”的所有实例,无论是 order 还是其他具有“type”=“notText”的对象。

有人知道如何做到这一点吗?

标签: javascriptarrays

解决方案


I'd suggest using Array.reduce again, starting with an empty array.

If the last item in the array we build up is of type 'text', append the current item, otherwise just add it to the array:

const arrayOfObj = [ { "type": "text", "text": "=" }, { "type": "text", "text": " " }, { "type": "text", "text": "S" }, { "type": "text", "text": "O" }, { "type": "notText", "attrs": { "id": 20, "data": "Something", } }, { "type": "text", "text": "H" }, { "type": "text", "text": "E" }, { "type": "text", "text": "Y" }, { "type": "notText", "attrs": { "id": 20, "data": "Other", } }, { "type": "text", "text": "=" }, { "type": "text", "text": "T" }, { "type": "text", "text": "O" }, ]
    
const result = arrayOfObj.reduce((acc, curr) => {
    // If the last item was of type 'text' _and_ the current item is too.. append the text
    if (acc[acc.length-1]?.type === 'text' && curr.type === 'text') { 
        acc[acc.length-1].text += curr.text;
    } else {
        // Either current or last item in array was not type 'text' 
        acc.push(curr)
    }
    return acc;
}, []);

console.log('Result:', result);


推荐阅读