結論
マージ関数
const reduceSameProducts = (Orders: Order[]) => {
return Orders.reduce<Order[]>((acc, currentOrder) => {
// ここはマージする条件
if (acc[acc.length-1] &&
acc[acc.length-1].name === currentOrder.name
) {
// マージする処理
const processedOrder: Order = {
...acc[acc.length-1],
quantity: acc[acc.length-1].quantity + currentOrder.quantity,
}
return [processedOrder]
} else {
// マージ対象ではなかったらスキップ
acc.push(currentOrder);
return acc;
}
}, []);
}
解説
以下のOrder
データオブジェクトを想定します。
Order
type Order = {
name: string;
price: number;
quantity: number;
}
そして以下のようなOrder[]
があったとします。
Order[]
const orders: Order[] = [
{ name: 'トマト', price: 100, quantity: 1 },
{ name: 'トマト', price: 100, quantity: 2 },
{ name: 'マンゴー', price: 200, quantity: 1 },
{ name: 'イチゴ', price: 250, quantity: 3 }
];
トマトが被っていますね。
これを以下のようにマージしたい。
マージ
[
{ name: 'トマト', price: 100, quantity: 3 },
{ name: 'マンゴー', price: 200, quantity: 1 },
{ name: 'イチゴ', price: 250, quantity: 3 }
];
トマトの個数をまとめました。
しかしこれをまとめるのが意外と難しい。
現在の要素と一つ前の要素を比較してゴニョゴニョする必要がありそうです。
reduce
が使えそうです。
最初の要素は空配列にします。
最初
type Order = {
name: string; // 商品名
price: number; // 値段
quantity: number; // 個数
}
const orders: Order[] = [
{ name: 'トマト', price: 100, quantity: 1 },
{ name: 'トマト', price: 100, quantity: 2 },
{ name: 'マンゴー', price: 200, quantity: 1 },
{ name: 'イチゴ', price: 250, quantity: 3 }
];
const reduceSameProducts = (Orders: Order[]) => {
return Orders.reduce<Order[]>((acc, currentOrder) => {}, []);
}
acc
は accumulator
です。前回の
(acc, currentOrder) => {}
の呼び出し結果です。
商品名が一致しているかどうかで処理を変更するので、そうでない場合は現在の値をそのまま結果に突っ込む必要があります。
ここで以下のように処理を書きます。
ステップ1
const reduceSameProducts = (Orders: Order[]) => {
return Orders.reduce<Order[]>((acc, currentOrder) => {
// ここはマージする条件
if (acc[acc.length-1] &&
acc[acc.length-1].name === currentOrder.name
) {
} else {
// マージ対象ではなかったらスキップ
acc.push(currentOrder);
return acc;
}
}, []);
}
acc[acc.length-1]
は、1回目の時に undefined
になるため、そこの条件分岐のために入れています。
acc[acc.length-1].name === currentOrder.name
は一つ前の結果と比べるための条件です。
マージする条件は以下でも可です。
const existingOrder = acc.find(order => order.name === currentOrder.name);
そして実際のマージ処理です。
一つ前の結果(現在の値でもいいです)の処理しないプロパティを展開して、対象のプロパティを処理します。
const processedOrder: Order = {
...acc[acc.length-1],
quantity: acc[acc.length-1].quantity + currentOrder.quantity,
}
こうすることで、以下のように値が変わります。
結果
[{
"name": "トマト",
"price": 100,
"quantity": 3
}, {
"name": "マンゴー",
"price": 200,
"quantity": 1
}, {
"name": "イチゴ",
"price": 250,
"quantity": 3
}]
おわりに
もっといいやり方があったら教えてください。