Подтвердить что ты не робот

Как получить объединение нескольких immutable.js списков

Итак, у меня есть список a:

let a = Immutable.List([1])

и список b:

let b = Immutable.List([2, 3])

Я хочу получить из них List union === List([1, 2, 3]).

Я пытаюсь merge их кулак:

let union = a.merge(b); // List([2, 3])

Похоже, что метод merge работает с индексами, а не со значениями, поэтому переопределяет первый элемент List a с первым элементом List b. Итак, мой вопрос - это самый простой способ получить объединение нескольких списков (в идеале без повторения их и других дополнительных операций).

4b9b3361

Ответ 1

Вы правы насчет слияния. Merge обновит индекс с текущим значением списка слияния. Так что в вашем случае у вас был

[0] = 1

и объединил его с

[0] = 2
[1] = 3

который закончил переписывание [0]=1 с помощью [0]=2, а затем установил [1]=3, в результате получив наблюдаемый массив [2,3] после слияния.

Очень простой подход к решению этого вопроса заключается в использовании concat

var a = Immutable.List([1]);
var b = Immutable.List([2,3]); 

var c = a.concat(b);

И это сработает для этой ситуации. Однако, если ситуация более сложная, это может быть неверно. Например,

var a = Immutable.List([1,4]);
var b = Immutable.List([2,3,4]); 

это даст вам два 4, которые больше не являются технически объединением. К сожалению, в Immutable нет союза. Простым способом реализации было бы установить каждое значение в каждом списке как ключ к объекту, а затем взять эти ключи в результате объединения.

jsFiddle Demo

function union(left,right){
 //object to use for holding keys
 var union = {};

 //takes the first array and adds its values as keys to the union object
 left.forEach(function(x){
  union[x] = undefined;
 });

 //takes the second array and adds its values as keys to the union object
 right.forEach(function(x){
  union[x] = undefined;
 });

 //uses the keys of the union object in the constructor of List 
 //to return the same type we started with
 //parseInt is used in map to ensure the value type is retained
 //it would be string otherwise
 return Immutable.List(Object.keys(union).map(function(i){ 
  return parseInt(i,10); 
 }));
}

Этот процесс O(2(n+m)). Любой процесс, который использует contains или indexOf, в конечном итоге будет O(n^2), поэтому именно здесь были использованы ключи.

позднее редактирование

Hyper-производительный

function union(left,right){
    var list = [], screen = {};
    for(var i = 0; i < left.length; i++){
        if(!screen[left[i]])list.push(i);
        screen[left[i]] = 1;
    }
    for(var i = 0; i < right.length; i++){
        if(!screen[right[i]])list.push(i);
        screen[right[i]] = 1;
    }
    return Immutable.List(list);
}

Ответ 2

На самом деле Immutable.js имеет объединение - это для структуры данных Set:

https://facebook.github.io/immutable-js/docs/#/Set/union

Самое замечательное в Immutable.js - это помочь внедрить в JS больше функциональных программных конструкций, в этом случае общий интерфейс и способность абстрагировать типы данных. Поэтому, чтобы вызвать объединение в ваших списках - преобразовать их в наборы, использовать union и затем преобразовать их обратно в списки:

var a = Immutable.List([1, 4]);
var b = Immutable.List([2, 3, 4]); 
a.toSet().union(b.toSet()).toList(); //if you call toArray() or toJS() on this it will return [1, 4, 2, 3] which would be union and avoid the problem mentioned in Travis J answer.