组合Underscore.js中相同的两个对象

时间:2016-09-06 16:29:45

标签: javascript underscore.js

我有一个对象数组,数组中的两个对象是相同的(最后两个):

 [
        {
            "facilities": 1,
            "place": "Campbellsville",
            "state": "KY",
            "lat": 37.34595018,
            "lon": -85.34544564
        },
        {
            "facilities": 1,
            "place": "Lexington",
            "state": "KY",
            "lat": 38.040584,
            "lon": -84.503716
        },
        {
            "facilities": 1,
            "place": "Hebron",
            "state": "KY",
            "lat": 39.066147,
            "lon": -84.703189
        },
        {
            "facilities": 1,
            "place": "Hebron",
            "state": "KY",
            "lat": 39.066147,
            "lon": -84.703189
        }
    ]

我想将两个相同的对象组合成一个对象,其中'facilities'键是每个'facility'值的总和:

    [
        {
            "facilities": 2,
            "place": "Campbellsville",
            "state": "KY",
            "lat": 37.34595018,
            "lon": -85.34544564
        },
        {
            "facilities": 1,
            "place": "Lexington",
            "state": "KY",
            "lat": 38.040584,
            "lon": -84.503716
        },
        {
            "facilities": 2,
            "place": "Hebron",
            "state": "KY",
            "lat": 39.066147,
            "lon": -84.703189
        },
    ]

有没有办法在javascript中使用Node或者使用Node的underscore.js?

6 个答案:

答案 0 :(得分:3)

普通js的解决方案:

我们会遍历项目数组,并根据指定的键值检查重复项。

当我们遇到我们之前遇到的价值时,这表明我们发现了重复。如果对象是新的,我们存储该事件。如果我们之前已经看过它,我们将合并这两个对象并存储我们的合并表示。

为了能够快速检查我们之前是否看到过相同的物体,我们将使用参考物体。该对象包含每个唯一键的项目。

在这个例子中我定义:

  • 合并策略:这保留了递增facilities道具的逻辑
  • 比较键:它包含确定"相似性的属性名称"在两个对象之间
  • 将对象转换为数组的实用工具方法



// Take an array of objects, compare them by `key`, merge if the `key`
// is not unique, return a new array.
var mergeDuplicatesByKey = function(items, mergeStrat, key) {
  return objValues(items.reduce(function(result, item) {
    var id = item[key];
    if (!result[id]) {
      result[id] = item;
    } else {
      result[id] = mergeStrat(result[id], item);
    }

    return result;
  }, {}));
};

// Our merge strategy: 
//  - create a new object
//  - add all of item1 and item2's properties
//  - sum the facilities prop
var merge = function(item1, item2) {
  return Object.assign({}, item1, item2, {
    facilities: item1.facilities + item2.facilities
  });
};

// The example data:
var data = [{
  "facilities": 1,
  "place": "Campbellsville",
  "state": "KY",
  "lat": 37.34595018,
  "lon": -85.34544564
}, {
  "facilities": 1,
  "place": "Lexington",
  "state": "KY",
  "lat": 38.040584,
  "lon": -84.503716
}, {
  "facilities": 1,
  "place": "Hebron",
  "state": "KY",
  "lat": 39.066147,
  "lon": -84.703189
}, {
  "facilities": 1,
  "place": "Hebron",
  "state": "KY",
  "lat": 39.066147,
  "lon": -84.703189
}];

// Call merge method with our own strategy, comparing items by `place`
console.log(mergeDuplicatesByKey(data, merge, "place"));


// Utils:
// Return the values for each key in in an object
function objValues(obj) {
  return Object.keys(obj).map(function(key) {
    return obj[key];
  });
};




答案 1 :(得分:1)

一个选项(需要两次迭代)就是将阵列缩小到一个关键的对象(这样你就可以总结设施)。你可以在那里停下来,只是迭代生成的对象,或者如果你需要它作为求和数组运行Object.keys并只返回存储在每个键上的对象。

缩小为对象:

var reduced = facilities.reduce(function(p, c) {
  if (p[c.place]) p[c.place].facilities++;
  else p[c.place] = c;
  return p;
}, {});

获取总和值:

Object.keys(reduced).map(function(item) { return reduced[item] });



var facilities =  [
  {
    "facilities": 1,
    "place": "Campbellsville",
    "state": "KY",
    "lat": 37.34595018,
    "lon": -85.34544564
  },
  {
    "facilities": 1,
    "place": "Lexington",
    "state": "KY",
    "lat": 38.040584,
    "lon": -84.503716
  },
  {
    "facilities": 1,
    "place": "Hebron",
    "state": "KY",
    "lat": 39.066147,
    "lon": -84.703189
  },
  {
    "facilities": 1,
    "place": "Hebron",
    "state": "KY",
    "lat": 39.066147,
    "lon": -84.703189
  }
];

var reduced = facilities.reduce((p, c) => {
  if (p[c.place]) p[c.place].facilities++;
  else p[c.place] = c;
  return p;
}, {});

console.log(reduced);

var summedArray = Object.keys(reduced).map(function(item) { return reduced[item];
});

console.log(summedArray);




答案 2 :(得分:1)

首先,根据您所需的情况对复合键进行分组:

var keyDel = '|';
var groups = _.groupBy(list, function(value){
    return value.place + keyDel + value.state + keyDel + value.lat + value.lon;
});

然后将每个组成员合并为一个,更新计数:

var data = _.map(groups, function(group){
    return {
        facilities: group.length,
        place: group[0].place,
        state: group[0].state,
        lat: group[0].lat,
        lon: group[0].lon
    }
});

答案 3 :(得分:0)

这是我从另一个解决类似问题的堆栈溢出问题中收集的函数。它是在javascript中。

var compare = function (json1, json2) {
    var i, l, leftChain, rightChain;

    function compare2Objects (x, y) {
        var p;

        // remember that NaN === NaN returns false
        // and isNaN(undefined) returns true
        if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
            return true;
        }

        // Compare primitives and functions.
        // Check if both arguments link to the same object.
        // Especially useful on the step where we compare prototypes
        if (x === y) {
            return true;
        }

        // Works in case when functions are created in constructor.
        // Comparing dates is a common scenario. Another built-ins?
        // We can even handle functions passed across iframes
        if ((typeof x === 'function' && typeof y === 'function') ||
        (x instanceof Date && y instanceof Date) ||
        (x instanceof RegExp && y instanceof RegExp) ||
        (x instanceof String && y instanceof String) ||
        (x instanceof Number && y instanceof Number)) {
            return x.toString() === y.toString();
        }

        // At last checking prototypes as good as we can
        if (!(x instanceof Object && y instanceof Object)) {
            return false;
        }

        if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
            return false;
        }

        if (x.constructor !== y.constructor) {
            return false;
        }

        if (x.prototype !== y.prototype) {
            return false;
        }

        // Check for infinitive linking loops
        if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
            return false;
        }

        // Quick checking of one object being a subset of another.
        // todo: cache the structure of arguments[0] for performance
        for (p in y) {
            if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
                return false;
            }
            else if (typeof y[p] !== typeof x[p]) {
                return false;
            }
        }

        for (p in x) {
            if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
                return false;
            }
            else if (typeof y[p] !== typeof x[p]) {
                return false;
            }

            switch (typeof (x[p])) {
                case 'object':
                case 'function':

                    leftChain.push(x);
                    rightChain.push(y);

                    if (!compare2Objects (x[p], y[p])) {
                        return false;
                    }

                    leftChain.pop();
                    rightChain.pop();
                    break;

                default:
                    if (x[p] !== y[p]) {
                        return false;
                    }
                    break;
            }
        }

        return true;
    }
    leftChain = []; //Todo: this can be cached
    rightChain = [];
    return (!compare2Objects(json1, json2));
}

我用它来比较Backbone模型(取决于underscore.js)

答案 4 :(得分:0)

简单而优雅。如果你愿意,可以更好地改变或评论。我使用了一些es6。

var _ = require('underscore');

// Check if array arr contains object obj
function exists(arr, obj) {
    var found = false;

    arr.forEach((item) => {
        if (_.isMatch(item, obj)) {
            found = true;
        }
    });

    return found;
}

var final = [];

original.forEach((obj) => {

    if (exists(final, obj)) {
        var index = _.findIndex(final, finalObj => _.isMatch(finalObj, obj)) 
        ++final[index].facilities
    } else {
        final.push(obj);
    }

});

return final;

答案 5 :(得分:0)

var list = [ { "facilities": 1, "place": "Campbellsville", "state": "KY", "lat": 37.34595018, "lon": -85.34544564 }, { "facilities": 1, "place": "Lexington", "state": "KY", "lat": 38.040584, "lon": -84.503716 }, { "facilities": 1, "place": "Hebron", "state": "KY", "lat": 39.066147, "lon": -84.703189 }, { "facilities": 1, "place": "Hebron", "state": "KY", "lat": 39.066147, "lon": -84.703189 } ] var uniqueList = _.uniq(list, function(item) { return item.toString(); }); /* uniqueList will be: { "facilities": 1, "place": "Campbellsville", "state": "KY", "lat": 37.34595018, "lon": -85.34544564 }, { "facilities": 1, "place": "Lexington", "state": "KY", "lat": 38.040584, "lon": -84.503716 }, { "facilities": 1, "place": "Hebron", "state": "KY", "lat": 39.066147, "lon": -84.703189 } */ 接受回电

{{1}}

如果将项目转换为String,则应该能够检测到重复。

注意:

  1. 用于比较的回调返回值
  2. 具有唯一返回值的第一个比较对象,用作唯一
  3. underscorejs.org演示没有回调用法
  4. lodash.com显示用法
相关问题