Об этих проблемах легче думать небольшими шагами, и мне нравится использовать функциональное программирование для обработки данных. Во-первых, давайте извлечем фрукты и овощи из остальных.
const produce = data.filter(entry => ["fruit", "veg"].includes(entry.type));
const remainder = data.filter(entry => !["fruit", "veg"].includes(entry.type));
Технически мы могли бы построить оба сразу с forEach
вместо вызова фильтра дважды, но я бы сказал, что ясность здесь превосходит эффективность.
Затем мы можем объединить фрукты и овощи с помощью функции .reduce
и умного использования спреда ...
.
const mergedItems = produce.reduce((acc, entry) => [...acc, ...entry.items], []);
Наконец, мы можем объединить все это в новый объект снова использует спредовую нотацию:
const result = [
{ type: "veg", items: mergedItems },
...remainder
];
Там у вас это есть. Вот результат:
const data = [
{ type: 'fish', weight: '2kg' },
{ type: 'veg', items: ['carrot', 'cabbage', 'pea'] },
{ type: 'fruit', items: ['apple', 'pear', 'orange' ]}
];
const produce = data.filter(entry => ["fruit", "veg"].includes(entry.type));
const remainder = data.filter(entry => !["fruit", "veg"].includes(entry.type));
const mergedItems = produce.reduce((acc, entry) => [...acc, ...entry.items], []);
const result = [
{ type: "veg", items: mergedItems },
...remainder
];
console.log(result);
РЕДАКТИРОВАТЬ: Вот несколько пояснений, основанных на комментариях.
Q: Есть ли в стороне, чтобы сохранить свойство от первоначального veg obj в конечном результате без его жесткого кодирования?
Если вы не возражаете изменить исходную запись type="veg"
, вы можете вместо этого перезаписать ее свойство items только для включения в нее фруктов. Но этот вопрос звучит так, как будто вы знаете, что есть ровно одна овощная и одна фруктовая запись, и в этом случае приведенный выше код был сложен даром, и мы могли бы просто использовать это:
const data = [
{ type: 'fish', weight: '2kg' },
{ type: 'veg', price: "3.00", items: ['carrot', 'cabbage', 'pea'] },
{ type: 'fruit', items: ['apple', 'pear', 'orange' ]}
];
const vegEntry = data.find(entry => entry.type === "veg");
const fruitIndex = data.findIndex(entry => entry.type === "fruit");
vegEntry.items = [...vegEntry.items, ...data[fruitIndex].items];
data.splice(fruitIndex, 1);
console.log(data);
Это добавляет элементы фруктов к элементам записи овощей и удаляет запись фруктов, таким образом сохраняя все свойства записи овощей.
Если для некоторых Если вы не хотите изменять данные на месте и предпочитаете создать новый объект результата, вы должны изменить его на:
const data = [
{ type: 'fish', weight: '2kg' },
{ type: 'veg', price: "3.00", items: ['carrot', 'cabbage', 'pea'] },
{ type: 'fruit', items: ['apple', 'pear', 'orange' ]}
];
const vegIndex = data.findIndex(entry => entry.type === "veg");
const fruitIndex = data.findIndex(entry => entry.type === "fruit");
const newVegEntry = {...data[vegIndex]};
newVegEntry.items = [...newVegEntry.items, ...data[fruitIndex].items];
const result = [...data];
result[vegIndex] = newVegEntry;
result.splice(fruitIndex, 1);
console.log(result);
Если это не работает в вашем браузере, это может быть связано с синтаксисом {...data[vegIndex]}
, который является немного более современным. Возможно, вы захотите использовать Object.assign({}, data[vegIndex]}
вместо этого, чтобы создать поверхностную копию записи veg.