如何按值从不可变的 js 映射中获取特定对象?

How do I get a specific object from an immutable js map by value?

我从对象列表创建了一个不可变映射(使用 Immutable-JS):

var result = [{'id': 2}, {'id': 4}];
var map = Immutable.fromJS(result);

现在我想用 id = 4 获取对象。

有没有比这更简单的方法:

var object = map.filter(function(obj){
 return obj.get('id') === 4
}).first();

有没有更简单的方法?我不知道。但你可以编写自己的函数。这样的事情应该有效:

var myFunc = function(id){

    var object = map.filter(function(obj){return obj.get('id') === id}).first();

    return object;
}

那么你只需要做:
var myObj = myFunc(4);

本质上,不是:您正在按值执行列表查找,而不是按索引,因此它将始终是线性遍历。

一个改进是使用 find 而不是 filter:

var result = map.find(function(obj){return obj.get('id') === 4;});

首先要注意的是,您实际上并不是在创建地图,而是在创建列表:

var result = [{'id': 2}, {'id': 4}];
var map = Immutable.fromJS(result);

Immutable.Map.isMap(map); // false
Immutable.List.isList(map); // true

为了创建地图,您可以在 toJS 调用 (docs) 中使用 reviver 参数,但它肯定不是最直观的 api,或者你可以做类似的事情:

// lets use letters rather than numbers as numbers get coerced to strings anyway
var result = [{'id': 'a'}, {'id': 'b'}];
var map = Immutable.Map(result.reduce(function(previous, current) { 
    previous[ current.id ] = current;
    return previous;
}, {}));

Immutable.Map.isMap(map); // true

现在我们有一个合适的 Immutable.js 地图,它有一个 get 方法

var item = Map.get('a'); // {id: 'a'}

保证数组的顺序可能很重要。如果是这样的话:

  1. 使用 OrderedMap
  2. 在源数组的每次迭代中对 OrderedMap 执行 set 方法

下面的示例使用 "withMutations" 以获得更好的性能。

var OrderedMap = Immutable.OrderedMap


// Get new OrderedMap
function getOm(arr) {
    return OrderedMap().withMutations(map => {
        arr.forEach(item => map.set(item.id, item))
    })
}

// Source collection
var srcArray = [
    {
        id: 123,
        value: 'foo'
    },
    {
        id: 456,
        value: 'bar'
    }
]


var myOrderedMap = getOm(srcArray)

myOrderedMap.get(123)
// --> { id: 123, value: 'foo' }

myOrderedMap.toObject()
// --> { 123: {id: 123, value: 'foo'}, 456: {id: 456, value: 'bar'} }

myOrderedMap.toArray()
// --> [ {id: 123, value: 'foo'}, { id: 456, value: 'bar' } ]

当对数组使用 fromJS 时,您将得到 List 而不是 map。如果您创建地图会更好更容易。以下代码会将结果转换为不可变映射。

  const map = result.reduce((map, json) =>
    map.set(json.id, Immutable.fromJS(json))
  , Map());

现在,您可以

   map.get('2');   //{'id': 2}

注意,如果结果有嵌套结构,如果结果有数组,它将是上面代码的List。

使用 ES2015 语法(和常量):

const result = map.find(o => o.get('id') === 4);