首页 > 解决方案 > 将点符号字符串转换为对象并查找引用对象

问题描述

我有一个点表示的数组,例如:

var base = ['a.b.c','a.e','h'];

我还有一个参考对象:

var reference = { 
  a: { 
    b: { 
      c:"Hello", 
      d:"you" 
    }, 
    e:"beautiful",
    f:"and"
  },
  g:"kind",
  h:"World" 
};

我需要从基本标记的字符串中构建一个对象并从参考对象中获取值。不幸的是,我无法更改基础或参考。

我让它适用于数组的每个单独部分,但问题是当我尝试合并对象时。它用ae覆盖值abc

我想要的输出是:

var desiredOutput = { 
  a: { 
    b: { 
      c:"Hello" 
    }, 
    e:"beautiful" 
  }, 
  h:"World" 
};

但是,使用下面的代码,我的输出是:

var output = { 
    a: { 
        e: "beautiful" 
    },
    h: "World" 
};

任何帮助,将不胜感激。我仅限于 < ES5,但Object.assign如果需要,可以使用一些 polyfill。

function convert(base,reference) {
    var obj = {};

    var getObjectValue = function(string, reference) {
        var i = 0;
        while (reference && i < string.length) {
            reference = reference[string[i++]];
        }
        return reference;
    };

    for (var n = 0; n < base.length; n++) {    
        var s = base[n].split("."),
            x = obj;

        for(var i = 0; i < s.length-1; i++) {
            x = x[s[i]] = {}; 
        }

        x[s[i]] = getObjectValue(s,reference);
    }
    return obj;
}

var base = ['a.b.c','a.e','h'];

var reference = { 
  a: { 
    b: { 
      c:"Hello", 
      d:"you" 
    }, 
    e:"beautiful",
    f:"and"
  },
  g:"kind",
  h:"World" 
};

var desiredOutput = { 
  a: { 
    b: { 
      c:"Hello" 
    }, 
    e:"beautiful" 
  }, 
  h:"World" 
};

console.log(convert(base,reference));

标签: javascriptobjectappendassign

解决方案


和你的

x = x[s[i]] = {}; 

s[i]即使它已经被填充,您也无条件地覆盖该属性。仅当该属性中不存在另一个对象时才分配一个新对象。

if (x[s[i]]) {
  x = x[s[i]];
} else {
  x = x[s[i]] = {};
}

function convert(base,reference) {
    var obj = {};

    var getObjectValue = function(string, reference) {
        var i = 0;
        while (reference && i < string.length) {
            reference = reference[string[i++]];
        }
        return reference;
    };

    for (var n = 0; n < base.length; n++) {    
        var s = base[n].split("."),
            x = obj;

        for(var i = 0; i < s.length-1; i++) {
            if (x[s[i]]) {
              x = x[s[i]];
            } else {
              x = x[s[i]] = {};
            }
        }

        x[s[i]] = getObjectValue(s,reference);
    }

    return obj;

}

var base = ['a.b.c','a.e','h'];

var reference = { 
  a: { 
    b: { 
      c:"Hello", 
      d:"you" 
    }, 
    e:"beautiful",
    f:"and"
  },
  g:"kind",
  h:"World" 
};

var desiredOutput = { 
  a: { 
    b: { 
      c:"Hello" 
    }, 
    e:"beautiful" 
  }, 
  h:"World" 
};


console.log(convert(base,reference));

这就是我的处理方式:

var base = ['a.b.c','a.e','h'];
var reference = { 
  a: { 
    b: { 
      c:"Hello", 
      d:"you" 
    }, 
    e:"beautiful",
    f:"and"
  },
  g:"kind",
  h:"World" 
};

const results = {};
// Helper function to get the nested value from an array of properties:
const getVal = props => props.reduce((a, b) => a[b], reference);
for (const propStr of base) {
  // Turn string into an array of properties:
  const props = propStr.split('.');
  // Get nested value to assign at the end:
  const val = getVal(props);
  // Get last property to assign on the last object:
  const lastProp = props.pop();
  let obj = results;
  // Iterate through to the nested object on the `results`,
  // creating objects on the way only if they don't exist yet:
  while (props.length) {
    const prop = props.shift();
    if (obj[prop]) obj = obj[prop];
    else {
      obj[prop] = {};
      obj = obj[prop];
    }
  }
  obj[lastProp] = val;
}
console.log(results);


推荐阅读