在数组的对象内对相同值的副本进行分组

时间:2017-06-11 02:11:31

标签: javascript

[{
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Confirm": 0
}, {
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Expired": 25
}, {
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Pending": 390
}, {
    "_id": {
        "year": 2017,
        "month": 5
    },
    "Pending": 1400
}]

上面的数组包含相同的月份和年份值。从MongoDB Aggregate生成。我想将它们合并到一个对象中,并保留它们拥有的任何键和值。

预期产出:

[{
    month: 4,
    year: 2017,
    Expired: 25,
    Pending: 390
}, {
    month: 5,
    year: 2017,
    Pending: 1400
}]

我更喜欢最快的执行实现。欢迎Underscorejs或本地人。感谢

3 个答案:

答案 0 :(得分:1)

这需要一点点分开,但它是线性的:

const ary = [{
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Confirm": 0
}, {
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Expired": 25
}, {
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Pending": 390
}, {
    "_id": {
        "year": 2017,
        "month": 5
    },
    "Pending": 1400
}];

const result = Object.values(ary.reduce((acc, cur) => {
    const { month, year } = cur._id;
    const key = `${month}-${year}`;
    const obj = Object.assign({}, cur);
    delete obj._id;
    acc[key] = Object.assign(acc[key] || { month, year }, obj);
    return acc;
}, {}));

console.log(result);

答案 1 :(得分:0)

这在O(N * logN)中进行排序,O(N)用于合并json。 希望这对你有用!



var obj = [{
    _id: {
        year: 2017,
        month: 5,
    },
    Pending: 1400,
}, {
    _id: {
        year: 2017,
        month: 4,
    },
    Expired: 25,
}, {
    _id: {
        year: 2017,
        month: 4,
    },
    Pending: 390,
}, {
    _id: {
        year: 2017,
        month: 4,
    },
    Confirm: 0,
}];

function compare(a, b) {
    return a._id.year !== b._id.year
        ? a._id.year - b._id.year
        : a._id.month - b._id.month;
}

var sorted = obj.sort(compare);

function join(a, b) {
    return {
        _id: a._id,
        Pending: (a.Pending? a.Pending : 0) + (b.Pending? b.Pending : 0),
        Confirm: (a.Confirm? a.Confirm : 0) + (b.Confirm? b.Confirm : 0),
        Expired: (a.Expired? a.Expired : 0) + (b.Expired? b.Expired : 0),
    };
}

var compressed = sorted.filter(function (value, index) {
    if (!sorted[index + 1]) {
        return true;
    }
    if (compare(value, sorted[index + 1]) === 0) {
        sorted[index + 1] = join(value, sorted[index + 1]);
        return false;
    }
    return true;
});

console.log(compressed);

// if you want month and year formatted:

console.log(compressed.map(function (o) {
    const result = {
        month: o._id.month,
        year: o._id.year,
    };
    if (o.Pending !== undefined) result.Pending = o.Pending;
    if (o.Confirm !== undefined) result.Confirm = o.Confirm;
    if (o.Expired !== undefined) result.Expired = o.Expired;
    return result;
}));




答案 2 :(得分:0)

您可以使用Map进行分组,然后使用Array.from来提取最终对象:



function merge(data) {
    return Array.from(data.reduce( (acc, o) => {
        const k = o._id.year * 100 + o._id.month;
        const v = acc.get(k) || Object.assign({}, o._id);
        for (let prop in o) {
            if (prop !== '_id') v[prop] = o[prop];
        }            
        return acc.set(k, v);
    }, new Map), ([k, v]) => v);
}
// Sample data
const data = [{
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Confirm": 0
}, {
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Expired": 25
}, {
    "_id": {
        "year": 2017,
        "month": 4
    },
    "Pending": 390
}, {
    "_id": {
        "year": 2017,
        "month": 5
    },
    "Pending": 1400
}];

const result = merge(data);

console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }




相关问题