如何通过顺序和限制来计算多个数组的数组元素总数?

时间:2019-07-15 07:43:49

标签: javascript arrays node.js dictionary set

我有3种3种不同类型的阵列。每个数组都包含一个id的计数(可能与arrayOfB一样重复)。

每个id的count属性的极限值为10(该计数包括不同的类型。例如:如果unique1在A类型中具有10个计数,则当unique1的类型为B时,将不对其进行处理)。

const arrayOfA = [
    {
        "type": "A", "count": 10, "id": "UID1"
    },
    {
        "type": "A", "count": 20, "id": "UID2"
    },
    {
        "type": "A", "count": 1, "id": "UID4"
    },
];

const arrayOfB = [
    {
        "type": "B", "count": 5, "id": "UID1"
    },
    {
        "type": "B", "count": 5, "id": "UID3"
    },
];

const arrayOfC = [
    {
        "type": "C", "count": 6, "id": "UID1"
    },
    {
        "type": "C", "count": 6, "id": "UID4"
    },
    {
        "type": "C", "count": 3, "id": "UID2"
    },
    {
        "type": "C", "count": 3, "id": "UID3"
    },
]

输出如下:

Map {
  'UID1|A' => 10,
  'UID2|A' => 10,
  'UID4|A' => 1,
  'UID3|B' => 5,
  'UID4|C' => 6 }

我使用了一个集合来保存id,该id已经具有最大数量并映射以保存输出。

const maxed = new Set();
const elements = new Map();

arrayOfA.forEach(element => {
    if (element.count > 10) {
        maxed.add(`${element.id}`);
        elements.set(`${element.id}|${element.type}`, 10);
        console.log(elements)
        return;
    }

    if (elements.has(`${element.id}|${element.type}`)) {
        const newCount = elements.get(`${element.id}|${element.type}`) + element.count;
        newCount > 10 ? elements.set(`${element.id}|${element.type}`, 10) : elements.set(`${element.id}|${element.type}`, newCount);
        console.log(elements)
        return;
    }

    elements.set(`${element.id}|${element.type}`, element.count);
});

arrayOfB.forEach(element => {
    if (maxed.has(`${element.id}`)) {
        console.log(elements)
        return;
    }

    const countOfA = elements.has(`${element.id}|A`) ? elements.get(`${element.id}|A`) : 0;
    let newCount = countOfA + element.count;

    if (elements.has(`${element.id}|${element.type}`)) {
        newCount = newCount + element.get(`${element.id}|${element.type}`);
    }

    if (newCount > 10) {
        maxed.add(`${element.id}`);
        if ((10 - countOfA) > 0) elements.set(`${element.id}|${element.type}`, 10 - countOfA);
        console.log(elements)
        return;
    }

    elements.set(`${element.id}|${element.type}`, element.count);
})

arrayOfC.forEach(element => {
    if (maxed.has(`${element.id}`)) {
        console.log(elements)
        return;
    }

    const countOfA = elements.has(`${element.id}|A`) ? elements.get(`${element.id}|A`) : 0
    const countOfB = elements.has(`${element.id}|C`) ? elements.get(`${element.id}|C`) : 0

    let newCount = countOfA + countOfB + element.count;

    if (elements.has(`${element.id}|${element.type}`)) {
        newCount = newCount + element.get(`${element.id}|${element.type}`);
    }

    if (newCount > 10) {
        maxed.add(`${element.id}`);
        if ((10 - countOfA - countOfB) > 0); elements.set(`${element.id}|${element.type}`, 10 - countOfA - countOfB);
        console.log(elements)
        return;
    }

    elements.set(`${element.id}|${element.type}`, element.count);
})

我想问一下另一个更快的实现。我估计我的大O将是O(n)(n是3个数组的总长度)。如果数组的元素不包含相同的ID。

编辑: 非常感谢大家,但是好像有一个极端的案例。答案无法解决

var arrayOfA = [
    {
        "type": "A", "count": 10, "id": "UID1"
    },
    {
        "type": "A", "count": 20, "id": "UID2"
    },
    {
        "type": "A", "count": 1, "id": "UID4"
    },
];

const arrayOfB = [
    {
        "type": "B", "count": 5, "id": "UID1"
    },
    {
        "type": "B", "count": 5, "id": "UID3"
    },
    {
        "type": "B", "count": 1, "id": "UID3"
    },
];

var arrayOfC = [
    {
        "type": "C", "count": 6, "id": "UID1"
    },
    {
        "type": "C", "count": 6, "id": "UID4"
    },
    {
        "type": "C", "count": 3, "id": "UID2"
    },
    {
        "type": "C", "count": 3, "id": "UID3"
    },
]

在arrayOfB中,我的UID3发生了两次,因此您的答案似乎不适用于这种情况。

2 个答案:

答案 0 :(得分:1)

您可以将每个Set的{​​{1}}加起来,而不是将maxed用于id count,并将其用于以下所有数组。

id
const
    getKey = (...a) => a.join('|'),
    rawData = [{ type: "A", count: 10, id: "UID1" }, { type: "A", count: 20, id: "UID2" }, { type: "A", count: 1, id: "UID4" }],
    rawData3 = [{ type: "B", count: 5, id: "UID1" }, { type: "B", count: 5, id: "UID3" }],
    rawData2 = [{ type: "C", count: 6, id: "UID1" }, { type: "C", count: 6, id: "UID4" }, { type: "C", count: 3, id: "UID2" }, { type: "C", count: 3, id: "UID3" }],
    elements = new Map,
    sums = new Map;

[rawData, rawData3, rawData2].forEach(a => a.forEach(({ type, count, id }) => {
    var sum = sums.get(id) || 0,
        key = getKey(id, type);

    sums.set(id, sum + count);

    if (sum >= 10) return;
    if (sum + count > 10) {
        if (10 - sum > 0) elements.set(key, 10 - sum);
        return;
    }
    elements.set(key, count);
}));

[...elements].map(a => console.log(a.join(': ')));

答案 1 :(得分:1)

基于您不希望在预期结果集中包含“ B”的假设,两个嵌套循环可以提供所需的操作和过滤。

function getIdSummary(arrays) {

    const maxValue = 10;

    //Array of objects which we later conver to a map
    //The aim is ease of indexing during the iterations
    var summary = []


    //A heler to find if a maxed uid is found in the summary
    function isMaxed(uid) {
        return summary.some(item => {
            return item.uid === uid && item.count >= maxValue;
        })
    }



    //Iterate all the arrays
    arrays.forEach(anInputArray => {

        //Iterate each array
        anInputArray.forEach(item => {
            if (!isMaxed(item.id)) {
                summary.push({uid: item.id, type: item.type, count: item.count > maxValue ? 10 : item.count})
            }

        })

    })

    return new Map(summary.map(obj => {
        return [obj.uid + '|' + obj.type, obj.count]
    }))


}



var arrayOfA = [
    {
        "type": "A", "count": 10, "id": "UID1"
    },
    {
        "type": "A", "count": 20, "id": "UID2"
    },
    {
        "type": "A", "count": 1, "id": "UID4"
    },
];

const arrayOfB = [
    {
        "type": "B", "count": 5, "id": "UID1"
    },
    {
        "type": "B", "count": 5, "id": "UID3"
    },
];

var arrayOfC = [
    {
        "type": "C", "count": 6, "id": "UID1"
    },
    {
        "type": "C", "count": 6, "id": "UID4"
    },
    {
        "type": "C", "count": 3, "id": "UID2"
    },
    {
        "type": "C", "count": 3, "id": "UID3"
    },
]


var m = getIdSummary([arrayOfA, arrayOfB, arrayOfC]);

console.log(Array.from(m));