如何使用lodash修改JSON集合中的选择对象

时间:2015-03-03 00:50:28

标签: json coffeescript underscore.js lodash

我正在寻找一种高效的方法来根据参考数组中记录ID的存在来更新集合中的选定记录。例如,给定[1,2,5]的引用数组,我希望集合中的每个记录都具有$selected: true的属性。集合中的每条记录都会与视图中的复选框相关联,并会检查$selected项目(fiddle

我从下面的方法(coffeescript)开始,但我是Lodash的新手,所以我想我会要求一些反馈。另外,我不确定将$selected: false设置为备用记录的最简洁方法是什么?

# Whole Collection
collection = [
    {id:1, name: "one"},
    {id:2, name: "two"},
    {id:3, name: "three"},
    {id:4, name: "four"},
    {id:5, name: "five"}
]

# Mark subset as selected
for id in [1,2,5]
    _.where( collection, 'id':id ).forEach( (record) ->
        record.$selected = true
    )

这是一个小提琴...... http://jsfiddle.net/zd78e4bj/


修改 添加了对视图

中复选框的双向绑定$selected元素的引用

2 个答案:

答案 0 :(得分:0)

我会做这样的事情(抱歉,它不是CoffeScript,但你明白了):

var collection = [
    { id:1, name: 'one' },
    { id:2, name: 'two' },
    { id:3, name: 'three' },
    { id:4, name: 'four' },
    { id:5, name: 'five'}
];

var ids = [ 1, 2, 5 ];

_(collection)
    .indexBy('id')
    .at(ids)
    .each(_.ary(_.partialRight(_.assign, { $selected: true }), 1))
    .value();

console.log(collection);
// → 
// [
//   { id: 1, name: 'one', $selected: true },
//   { id: 2, name: 'two', $selected: true },
//   { id: 3, name: 'three' },
//   { id: 4, name: 'four' },
//   { id: 5, name: 'five', $selected: true }    
// ]

首先,我们使用indexBy()创建一个中间对象。密钥是id中的collection值。接下来,我们会通过at()我们感兴趣的ID。这会构建一个新的集合,其中只包含我们之后的ID。

最后一步是使用each()添加$selected属性。这是通过合并partialRight()assign()ary()来完成的。部分应用的参数是新的$selected属性。我们使用ary()来确保传递给each()的回调只有一个参数。

答案 1 :(得分:0)

您可以使用mapforEach功能在Lodash或本机JavaScript中执行所有操作。 Map创建一个新列表,forEach将改变现有列表。

这些的关键是转换功能。如果在{ids集合中存在或不存在,则此函数将$selected设置为true或false。

function mark(item) {
    item['$selected'] = (ids.indexOf(item.id) > -1);
    return item;
}

您可以使用以下方法构建更通用的转换器:

function markItemByList(list, property, searchField) {
    return function(item) {
        item[property] = (list.indexOf(item[searchField]) > -1);
        return item;
    }
}

Coffeescript将是:

markItemByList = (list, property, searchField) ->
    (item) ->
        item[property] = (list.indexOf(item[searchField])) > -1)
        item

如果你想要一个可变的实现:

function select(ids, collection) {
    collection.forEach(markItemByList(ids, '$selected', 'id'));
}

这是一个lodash不可变的实现:

function select(ids, collection) {
    return _.map(collection, markItemByList(ids, '$selected', 'id'));
}

这是一个纯JavaScript不可变的实现:

function select(ids, collection) {
    return collection.map(markItemByList(ids, '$selected', 'id'));
}

这是一个角度实现:

angular.forEach(collection, markItemsByList(ids, '$selected', 'id'));