Lodash合并。如何通过忽略空值来连接两个对象?

时间:2018-03-13 16:24:47

标签: javascript lodash

我的问题是我想混合我的初始应用程序状态和存储在其他地方的状态。如何使用忽略空值的Lodash连接javascript中的两个对象?这是我的代码:

const initialState = {
  form: [
    {
      name: "car",
      value: 45000
    },
    {
      name: "cat",
      value: 50
    },
    {
      name: "shipping",
      value: 5
    }
  ],
  option: "A",
  money: 500000
};

const storedState = {
  form: [
    null,
    null,
    {
      name: "shipping",
      value: 12
    }
  ],
  option: "B"
};

const preloadedState = _.merge({}, initialState, storedState);
console.log(preloadedState);

您可以从该console.log中看到的是该对象:

preloadedState = {
   form: [
     null,
     null,
     {
       name: "shipping",
       value: 12
     }
   ],
   option: "B",
   money: 500000
};

我希望始终忽略storedState中的空值,并保留initialState中的值。我怎样才能做到这一点?我想要的效果应该是:

preloadedState = {
   form: [
     {
       name: "car",
       value: 45000
     },
     {
       name: "cat",
       value: 50
     },
     {
       name: "shipping",
       value: 12
     }
   ],
   option: "B",
   money: 500000
};

请求帮助, 亚瑟

2 个答案:

答案 0 :(得分:1)

一种方法是使用compact()

_.compact(preloadedState.form)

但它也将删除其他" falsy"值,如0,false等。

其他选项是不使用

_.without(preloadedState.form, null)

在这两种情况下,合并结果。

如果您使用集合而不是数组,则filterreject也应该有效。

答案 1 :(得分:0)

此解决方案使用两种方法:

  1. mergeArrays将两个数组和reduces组合成一个地图。它使用相同的键合并对象。完成后,它会将Map转换回带有Map.values()spread syntax的数组。
  2. cleanMerge使用_.mergeWith()递归地组合对象。它还使用mergeArrays合并数组中的对象。 cleanMerge方法接受一个干净的回调,在这种情况下_.without()使用_.partialRight()将参数null附加到参数列表的末尾。
  3. 
    
    const initialState = {"form":[{"name":"car","value":45000},{"name":"cat","value":50},{"name":"shipping","value":5}],"option":"A","money":500000};
    const storedState = {"form":[null,null,{"name":"shipping","value":12}],"option":"B"};
    
    const mergeArrays = (o, s, prop, mergCB) => [... // spread the .values() iterator back to array
      [...o, ...s] // concat both arrays
      .reduce((r, o) => 
        _.isObject(o) ?
          // if object, add to Map with the prop as the key
          r.set(o[prop], mergCB(r.get(o[prop] || {}), o))
          : 
          // if not object, add to map with a symbol as the key, to preserve the value
          r.set(Symbol(), o),
        new Map())
      .values()]; // get the Map values iterator
    
    const cleanMerge = (o, s, cleanCB = _.identity) => _.mergeWith({}, o, s, (ov, sv) =>
      _.isArray(ov) ? 
        // if array, merge, and remove nulls
        cleanCB(mergeArrays(ov, sv, 'name', _.partialRight(cleanMerge, cleanCB)))
        : 
        // if not, let mergeWith handle the merge
        undefined);
      
    const preloadedState = cleanMerge(initialState, storedState, _.partialRight(_.without, null));
    
    console.log(preloadedState);
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
    &#13;
    &#13;
    &#13;