创建联系人数据阵列的已清理联系人对象

时间:2014-10-30 12:58:28

标签: javascript arrays object lodash

我有一个包含这样的对象的数组(简化版本,实际数组有更多数据):

[
    {
        id: '1',
        name: 'Joe',
        description: 'Student',
        locations: [ {
            type: 'home',
            value: '123'
        } ]
    },
    {
        id: '1',
        name: 'Joe',
        description: 'Farmer',
        locations: [ {
            type: 'home',
            value: '456'
        } ]
    },
    {
        id: '1',
        name: 'Joe',
        description: '',
        locations: [ {
            type: 'home',
            value: '123'
        } ]
    }
]

如何使用javascript(lodash)创建以下内容? :

{
    id: '1',
    name: 'Joe',
    description: 'Farmer',
    locations: [ {
        type: 'home',
        value: '123'
    }, {
        type: 'home',
        value: '456'
    } ]
}

目标是创建一个联系数据阵列的清理联系对象。所以它需要替换单个属性,如名称和描述,以防它们是空的。并推送像location这样的对象,以防在de locations array中找不到它。我确实使用_.merge得到了一些结果,问题是合并总是覆盖最后一个值并且不会推送新值,所以结果会是这样的:

{
    id: '1',
    name: 'Joe',
    description: '',
    locations: [ {
        type: 'home',
        value: '123'
    }]
}

2 个答案:

答案 0 :(得分:0)

关于如何处理冲突,你有很多未解决的问题。

  • 最后一个属性是否应该覆盖前一个属性?您想仅通过locations
  • 加入吗?
  • 加入仅由id完成吗?
  • 如何确定locations中的唯一性?是typevalue还是组合?

一旦您对这些问题有了答案,就可以使用以下内容:

// this will get you the items (from server/localstorage/whatever)
var items = getItems();

// group items by id (assuming that's our grouping denominator
var groupedItems = _.groupBy(items, 'id');

// then iterate through each item in group, and reduce them
var results = _.map(_.values(groupdItems), function(item) {
    var reduced =  _.reduce(item, function(result, num, key) {
        if (key === 'locations') {
           // join everything together, we'll unique them later
           result.locations = (result.locations || []).concat(num || []);  
        }
        else {
           // override all previous values for this key.
           // change this to improve behavior
           result[key] = num;
        }
        return result;
    }, {});
    // reduce locations to unique locations only
    // currently implemented by using JSON.stringified but could easily change
    reduced.locations = _.uniq(reduced.locations, function(loc) {
      return JSON.stringify(loc);
    });
    return reduced;
});

// results should now contains the transformed items.

答案 1 :(得分:0)

也许这应该足够了:

function customMerge(obj1, obj2) {
    for(var i in obj2) {
        if(typeof(obj1[i]) === 'object' && obj1[i].push) {
            for(var j in obj2[i]) {
                obj1[i].push(obj2[i][j]);
            }
            obj1[i] = arrayUnique(obj1[i]);
        } else {
            obj1[i] = obj2[i];
        }
    }
}

function arrayUnique(list, byKey) {
    var newList = [];
    var map = {};
    for(var i in list) {
        var data = list[i];
        var id = list[i].id || JSON.stringify(data);
        if(typeof(map[id]) === 'undefined') {
            map[id] = data;
        } else {
            customMerge(map[id], data);
        }
    }
    for(var i in map) {
        newList.push(map[i]);
    }
    return newList;
}

这会返回您期望的内容:

arrayUnique([
    {
        id: '1',
        name: 'Joe',
        description: 'Student',
        locations: [ {
            type: 'home',
            value: '123'
        } ]
    },
    {
        id: '1',
        name: 'Joe',
        description: 'Farmer',
        locations: [ {
            type: 'home',
            value: '456'
        } ]
    },
    {
        id: '1',
        name: 'Joe',
        description: '',
        locations: [ {
            type: 'home',
            value: '123'
        } ]
    }
])