{"ScriptPreparationCode":"var body = {\r\n items: [\r\n {\r\n goodsCode: \u0027004566\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027011774\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027004605\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027004606\u0027,\r\n quantity: 1,\r\n options: [],\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n {\r\n goodsCode: \u0027004566\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027011774\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027004605\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027004606\u0027,\r\n quantity: 1,\r\n options: [],\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n {\r\n goodsCode: \u0027004566\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027011774\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027004605\u0027,\r\n quantity: 1,\r\n options: [\r\n {\r\n goodsCode: \u0027004607\u0027,\r\n quantity: 1,\r\n options: [],\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n ],\r\n }","TestCases":[{"Name":"Map","Code":"function consolidateCartItems(items) {\r\n // \uB3D9\uC77C\uD55C \uC635\uC158 \uAD6C\uC870\uB85C \uADF8\uB8F9\uD551\uD558\uAE30 \uC704\uD55C \uD0A4 \uC0DD\uC131 \uD568\uC218\r\n const shapeKey = (item) =\u003E {\r\n // \uC635\uC158\uC774 \uC5C6\uB294 \uACBD\uC6B0 goodsCode\uB9CC\uC73C\uB85C \uD0A4 \uC0DD\uC131\r\n if (!item.options || item.options.length === 0) {\r\n return item.goodsCode;\r\n }\r\n // \uC635\uC158\uC774 \uC788\uB294 \uACBD\uC6B0, \uC790\uC2DD \uC635\uC158\uB4E4\uC758 \uD0A4\uB97C \uC7AC\uADC0\uC801\uC73C\uB85C \uC0DD\uC131 \uD6C4 \uC870\uD569\r\n const childKeys = item.options.map(shapeKey);\r\n return \u0060${item.goodsCode}[${childKeys.join(\u0027,\u0027)}]\u0060;\r\n };\r\n\r\n // \uADF8\uB8F9 \uC815\uBCF4 \uC800\uC7A5\uC6A9 Map: key=shapeKey, value=CartItemDto\r\n const optionGroups = new Map();\r\n\r\n // \uC785\uB825\uB41C \uAC01 \uC544\uC774\uD15C \uC21C\uD68C\r\n for (const item of items) {\r\n // \uD604\uC7AC \uD56D\uBAA9\uC758 \uC635\uC158 \uAD6C\uC870 \uD0A4 \uACC4\uC0B0\r\n const key = shapeKey(item);\r\n // \uC774\uBBF8 \uC635\uC158 \uADF8\uB8F9\uC5D0 \uC874\uC7AC\uD558\uB294\uC9C0 \uD655\uC778\r\n const optionGroup = optionGroups.get(key);\r\n\r\n if (!optionGroup) {\r\n // \uC635\uC158 \uADF8\uB8F9\uC774 \uC5C6\uB2E4\uBA74 \uC0C8 \uADF8\uB8F9\uC73C\uB85C \uCD08\uAE30\uD654\r\n optionGroups.set(key, {\r\n ...item,\r\n options: item.options ? [...item.options] : [], // \uC790\uC2DD \uC635\uC158 \uBCF5\uC0AC\r\n });\r\n } else {\r\n // \uC635\uC158 \uADF8\uB8F9\uC774 \uC774\uBBF8 \uC874\uC7AC\uD55C\uB2E4\uBA74 \uC218\uB7C9 \uB204\uC801\r\n optionGroup.quantity \u002B= item.quantity;\r\n // \uC635\uC158\uC774 \uC788\uC73C\uBA74 \uC790\uC2DD \uBC30\uC5F4\uC5D0 \uCD94\uAC00\r\n if (item.options) {\r\n optionGroup.options.push(...item.options);\r\n }\r\n }\r\n }\r\n\r\n const result = [];\r\n // Map\uC5D0 \uBAA8\uC778 \uC635\uC158 \uADF8\uB8F9 \uC815\uBCF4\uB97C \uAE30\uBC18\uC73C\uB85C CartItemDto \uC0DD\uC131\r\n for (const optionGroup of optionGroups.values()) {\r\n const consolidated = {\r\n goodsCode: optionGroup.goodsCode, // \uB300\uD45C goodsCode \uC124\uC815\r\n quantity: optionGroup.quantity, // \uB204\uC801\uB41C \uC218\uB7C9\r\n };\r\n\r\n // \uC790\uC2DD \uC635\uC158\uC774 \uC788\uB2E4\uBA74 \uC7AC\uADC0\uC801\uC73C\uB85C \uBCD1\uD569\uD558\uC5EC \uC635\uC158 \uD544\uB4DC \uC124\uC815\r\n if (optionGroup.options.length \u003E 0) {\r\n consolidated.options = consolidateCartItems(optionGroup.options);\r\n }\r\n\r\n result.push(consolidated);\r\n }\r\n\r\n // \uCD5C\uC885 \uBCD1\uD569\uB41C \uACB0\uACFC \uBC18\uD658\r\n return result;\r\n }\r\n\r\nconsolidateCartItems(body.items)","IsDeferred":false},{"Name":"Map \u002B stack","Code":"function consolidateCartItems(items) {\r\n // \u2500\u2500\u2500 1) \uB3D9\uC77C \uC635\uC158 \uAD6C\uC870 \uD310\uBCC4\uC6A9 \uD0A4 \uC0DD\uC131 \uD568\uC218 \u2500\u2500\u2500\r\n // \uC644\uC804\uD55C N\uCC28 \uAD6C\uC870\uB97C \uBB38\uC790\uC5F4\uB85C \uD45C\uD604\uD569\uB2C8\uB2E4.\r\n const shapeKey = (item) =\u003E {\r\n if (!item.options || item.options.length === 0) {\r\n return item.goodsCode;\r\n }\r\n // \uC790\uC2DD \uC635\uC158\uB4E4\uC758 \uD0A4\uB97C \uC7AC\uADC0 \uC0DD\uC131\r\n const childKeys = item.options.map(shapeKey);\r\n return \u0060${item.goodsCode}[${childKeys.join(\u0027,\u0027)}]\u0060;\r\n };\r\n\r\n // \u2500\u2500\u2500 2) \uC2A4\uD0DD \uCD08\uAE30\uD654 \u2500\u2500\u2500\r\n // rootOutput\uC5D0 \uCD5C\uC885 \uACB0\uACFC\uAC00 \uC313\uC785\uB2C8\uB2E4.\r\n const rootOutput = [];\r\n const stack = [{ items, outputArr: rootOutput }];\r\n\r\n // \u2500\u2500\u2500 3) \uC2A4\uD0DD \uBC18\uBCF5 \uCC98\uB9AC \u2500\u2500\u2500\r\n while (stack.length \u003E 0) {\r\n const { items: currItems, outputArr } = stack.pop();\r\n\r\n // \uD604\uC7AC \uB808\uBCA8\uC5D0\uC11C \uD0A4\uBCC4 \uADF8\uB8F9\uD654(Map) \u2192 {goodsCode, quantity, children[]}\r\n const groups = new Map();\r\n\r\n for (const item of currItems) {\r\n const key = shapeKey(item);\r\n const group = groups.get(key);\r\n\r\n if (!group) {\r\n // \uC2E0\uADDC \uADF8\uB8F9 \uC0DD\uC131\r\n groups.set(key, {\r\n goodsCode: item.goodsCode,\r\n quantity: item.quantity,\r\n // \uD558\uC704 \uC635\uC158\uC744 \uBAA8\uC544\uB458 \uBC30\uC5F4\r\n children: item.options ? [...item.options] : [],\r\n });\r\n } else {\r\n // \uAE30\uC874 \uADF8\uB8F9\uC5D0 \uC218\uB7C9 \uB204\uC801, \uC635\uC158 \uBCD1\uD569\r\n group.quantity \u002B= item.quantity;\r\n if (item.options) {\r\n group.children.push(...item.options);\r\n }\r\n }\r\n }\r\n\r\n // \uADF8\uB8F9\uBCC4\uB85C DTO \uC0DD\uC131, \uC635\uC158\uC774 \uC788\uC73C\uBA74 \uC2A4\uD0DD\uC5D0 \uB2E4\uC2DC \uD478\uC2DC\r\n for (const { goodsCode, quantity, children } of groups.values()) {\r\n const dto = { goodsCode, quantity };\r\n outputArr.push(dto);\r\n\r\n if (children.length \u003E 0) {\r\n // \uC774 dto\uC758 options\uAC00 \uCC44\uC6CC\uC9C8 \uBC30\uC5F4\uC744 \uBBF8\uB9AC \uC0DD\uC131\r\n dto.options = [];\r\n // \uC2A4\uD0DD\uC5D0 \uB123\uC5B4 \uD558\uC704 \uC635\uC158 \uB808\uBCA8\uC744 \uAC19\uC740 \uBC29\uC2DD\uC73C\uB85C \uCC98\uB9AC\r\n stack.push({ items: children, outputArr: dto.options });\r\n }\r\n }\r\n }\r\n\r\n // rootOutput\uC774 \uCD5C\uC885 \uACB0\uACFC\r\n return rootOutput;\r\n }\r\n\r\nconsolidateCartItems(body.items)","IsDeferred":false},{"Name":"lodash","Code":"function consolidateCartItems(items) {\r\n // 1) \uB3D9\uC77C \uC635\uC158 \uAD6C\uC870 \uD310\uBCC4 \uD0A4 \uC0DD\uC131 (\uC7AC\uADC0)\r\n const shapeKey = (item) =\u003E {\r\n if (!item.options || item.options.length === 0) {\r\n return item.goodsCode;\r\n }\r\n const childKeys = item.options.map(shapeKey);\r\n return \u0060${item.goodsCode}[${childKeys.join(\u0027,\u0027)}]\u0060;\r\n };\r\n\r\n // 2) lodash.groupBy \uB85C \uAC19\uC740 \uAD6C\uC870\uB07C\uB9AC \uBB36\uAE30\r\n const groups = _.groupBy(items, shapeKey);\r\n\r\n // 3) \uAC01 \uADF8\uB8F9\uBCC4\uB85C DTO \uC0DD\uC131 \uBC0F \uD558\uC704 \uC635\uC158(flatten) \uC7AC\uADC0 \uCC98\uB9AC\r\n return Object.values(groups).map((groupItems) =\u003E {\r\n // \uACF5\uD1B5 goodsCode\r\n const goodsCode = groupItems[0].goodsCode;\r\n // \uADF8\uB8F9 \uC804\uCCB4 \uC218\uB7C9 \uD569\uC0B0\r\n const quantity = _.sumBy(groupItems, \u0027quantity\u0027);\r\n // \uBAA8\uB4E0 \uC790\uC2DD \uC635\uC158\uC744 \uD558\uB098\uC758 \uBC30\uC5F4\uB85C \uBAA8\uC74C\r\n const allOptions = _.flatten(groupItems.map((i) =\u003E i.options ?? []));\r\n\r\n const consolidated = { goodsCode, quantity };\r\n if (allOptions.length \u003E 0) {\r\n // \uC790\uC2DD \uC635\uC158\uC774 \uC788\uC73C\uBA74 \uC7AC\uADC0 \uD638\uCD9C\r\n consolidated.options = consolidateCartItems(allOptions);\r\n }\r\n return consolidated;\r\n });\r\n }\r\n\r\nconsolidateCartItems(body.items)","IsDeferred":false}]}