简体   繁体   English

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

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

I created an immutable map (with Immutable-JS ) from a list of objects: 我从对象列表中创建了一个不可变的映射(使用Immutable-JS ):

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

Now i want to get the object with id = 4 . 现在我想得到id = 4的对象。

Is there an easier way than this: 有没有比这更简单的方法:

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

Essentially, no: you're performing a list lookup by value, not by index, so it will always be a linear traversal. 基本上,不是:您按值而不是索引执行列表查找,因此它始终是线性遍历。

An improvement would be to use find instead of filter : 改进将是使用find而不是filter

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

The first thing to note is that you're not actually creating a map, you're creating a list: 首先要注意的是,您实际上并没有创建地图,而是创建了一个列表:

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

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

In order to create a map you can use a reviver argument in your toJS call ( docs ), but it's certainly not the most intuitive api, alternatively you can do something like: 为了创建一个地图,您可以在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

Now we have a proper Immutable.js map which has a get method 现在我们有一个适当的Immutable.js地图,它有一个get方法

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

It may be important to guarantee the order of the array. 保证阵列的顺序可能很重要。 If that's the case: 如果是这样的话:

  1. Use an OrderedMap 使用OrderedMap
  2. Do a set method on the OrderedMap at each iteration of your source array 在源数组的每次迭代中在OrderedMap上执行set方法

The example below uses "withMutations" for better performance. 以下示例使用“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' } ]

When using fromJS for array, you'll get List not map. 当使用fromJS作为数组时,你将获得List not map。 It will be better and easier if you create a map. 如果您创建地图将会更好,更容易。 The following code will convert the result into Immutable map. 以下代码将结果转换为Immutable地图。

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

Now, you can 现在你可以

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

Note, if the result has nested structure and if that has array, it will be a List with the above code. 注意,如果结果具有嵌套结构,并且如果它具有数组,则它将是具有上述代码的List。

使用ES2015语法 (和常量):

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

Is there already a way thats easier? 有没有办法更容易? I don't know. 我不知道。 but you can write your own function. 但你可以编写自己的函数。 Something like this should work: 这样的事情应该有效:

var myFunc = function(id){

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

    return object;
}

Then you would just do: 然后你会做:
var myObj = myFunc(4);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM