ค้นหาเว็บไซต์

javascript - TypeScript: จัดกลุ่มรายการตามคุณสมบัติที่ใช้ร่วมกันและกำหนด groupID ให้พวกมัน


ฉันต้องการสร้างฟังก์ชันที่ทำสิ่งต่อไปนี้:

  • ใช้แอเรย์ของสินค้าเป็นอาร์กิวเมนต์
  • ส่งคืนอาเรย์ใหม่ของผลิตภัณฑ์ ซึ่งแต่ละผลิตภัณฑ์มีคุณสมบัติ groupId ใหม่
  • ผลิตภัณฑ์ที่แตกต่างกันจะใช้ groupId เดียวกันหากพวกเขามีคุณสมบัติทั่วไปเหมือนกัน โดยคุณสมบัติจะถูกกำหนดโดย groupIfIdentical

ดูโครงร่างฟังก์ชันที่นี่:

    function groupProductsBySharedAttributes(
      products: Product[],
      groupIfIdentical: (keyof Product)[],
      initialGroupId: string,
    ) {
      
    }

ผลิตภัณฑ์ที่มีคุณสมบัติเหมือนกันควรถูกจัดกลุ่มแบบนี้:

export function productsAreIdentical(
  prod1: Product,
  prod2: Product,
  groupIfIdentical: (keyof Product)[],
) {
  for (const key of groupIfIdentical) {
    if (prod1[key] !== prod2[key]) {
      return false
    }
    return true
  }
}

ตัวอย่าง :

const prods = [{
  country: 'china',
  material: 'steel',
  sku: 1453
},
{
  country: 'china',
  material: 'steel',
  sku: 4874
},
{
  country: 'japan',
  material: 'steel',
  sku: 4874
},
]


const result = groupProductsBySharedAttributes(prods, ['country', 'material'], 1001)

result = [
  {
  country: 'china',
  material: 'steel',
  sku: 1453,
  groupId: 1001
},
{
  country: 'china',
  material: 'steel',
  sku: 4874,
  groupId: 1001
},
{
  country: 'japan',
  material: 'steel',
  sku: 4874,
  groupId: 1002
}
]

คำตอบ #1

ในฟังก์ชัน groupProductsBySharedAttributes ก่อนอื่นคุณจะสร้างวัตถุ Map ที่เรียกว่า groupIdMap ซึ่งคุณจะเก็บเวอร์ชัน Stringify ของวัตถุที่มีคีย์ groupIfIdentical ของ product เป็นคีย์ และ groupId เป็นค่า นอกจากนี้คุณจะสร้างอาร์เรย์ใหม่ที่เรียกว่า groupedProducts ของสินค้าต่าง ๆ แต่หลังจากแทรก groupId แล้ว จากนั้นคุณจะวนลูปผ่านอาร์เรย์ products เพื่อตรวจสอบว่าคีย์ key มีอยู่ใน groupIdMap หรือไม่ ถ้ามี หมายความว่าพวกมันเหมือนกัน ถ้าไม่ ให้บันทึก key ใหม่และ groupId (หลังจากเพิ่มขึ้นหนึ่ง) และในทั้งสองกรณี ให้เพิ่มเข้าไปใน groupedProducts

interface Product {
    [key: string]: any;
}

function productsAreIdentical(
    prod1: Product,
    prod2: Product,
    groupIfIdentical: (keyof Product)[]
): boolean {
    for (const key of groupIfIdentical) {
        if (prod1[key] !== prod2[key]) {
            return false;
        }
    }
    return true;
}

function groupProductsBySharedAttributes(
    products: Product[],
    groupIfIdentical: (keyof Product)[],
    initialGroupId: string,
): Product[] {
    let groupId = parseInt(initialGroupId); // Convert initialGroupId to an integer for easy incrementation
    const groupedProducts: Product[] = [];
    const groupIdMap = new Map<string, number>(); // Maps a stringified key to a groupId

    products.forEach(product => {
        let foundGroup = false;
        for (const [key, id] of groupIdMap) {
            const keyAttributes = JSON.parse(key);
            if (productsAreIdentical(product, keyAttributes, groupIfIdentical)) {
                product.groupId = id;
                foundGroup = true;
                break;
            }
        }

        if (!foundGroup) {
            const key = JSON.stringify(
                groupIfIdentical.reduce((acc, attr) => {
                    acc[attr] = product[attr];
                    return acc;
                }, {} as Partial<Product>)
            );

            if (!groupIdMap.has(key)) {
                groupIdMap.set(key, groupId);
                product.groupId = groupId;
                groupId++;
            }
        }

        groupedProducts.push(product);
    });

    return groupedProducts;
}

// Example usage
const prods = [
    { country: 'china', material: 'steel', sku: 1453 },
    { country: 'china', material: 'steel', sku: 4874 },
    { country: 'japan', material: 'steel', sku: 4874 }
];

const result = groupProductsBySharedAttributes(prods, ['country', 'material'], '1001');
console.log(result);

สนามเด็กเล่น