繁体   English   中英

将数组转为更深层次的对象

[英]Turn array to a deep level of object

我有一个数组和一个这样的示例对象:

const array = ['a', 'b.c', 'c.d.e']

样本

const sample = {
  'aa': 'test',
  'a': 'value',
  'b': {
    'c': 'value'
  },
  'c': {
    'd': {
      'e': 'value'
    }
  },
  'e': {
    'f': {
      'g': {
        'h' : 'value'
      }
    }
  }
}

然后我想根据样本制作一个新对象。 结果应如下所示:

const newSample = {
  'aa': 'test',
  'a': 'oldvalue' + 1,
  'b': {
    'c': 'oldvalue' + 1
  },
  'c': {
    'd': {
      'e': 'oldvalue' + 1
    }
  },
  'e': {
    'f': {
      'g': {
        'h' : 'oldvalue'
      }
    }
  }
}

我正在考虑遍历数组并计算每个元素的长度。 但是,它不如数组和样本的级别增加那么有效。 有没有可以做得更好的算法?

 const array = ['a', 'b.c', 'cde'] const sample = { 'aa': test, 'a': 'value', 'b': { 'c': 'value' }, 'c': { 'd': { 'e': 'value' } }, 'e': { 'f': { 'g': { 'h' : 'value' } } } } const newSample = {} const transformer = (array) => { array.forEach(item => { const itemArr = item.split('.') if (itemArr.length === 1) { console.log(sample[itemArr[0]]) newSample[itemArr[0]] = sample[itemArr[0]] + 1 } // the condition goes on... }) } transformer(array) console.log(newSample)

谢谢,

您可以减少拆分的键并使用最后一个键保存分配的最后一个键。

 const keys = ['a', 'b.c', 'cde'] object = { a: 'value', b: { c: 'value' }, c: { d: { e: 'value' } }, e: { f: { g: { h : 'value' } } } }, transformer = (objec, keys) => keys.reduce((r, s) => { var path = s.split('.'), last = path.pop(), final = path.reduce((o, k) => o[k] = o[k] || {}, r); final[last] = (final[last] || '') + 1; // or whatever you need change return r; }, object); console.log(transformer(object, keys));
 .as-console-wrapper { max-height: 100% !important; top: 0; }

通过返回具有更改值的深层副本来实现非变异方法。

 function transformer(object, keys) { return Object.entries(object).reduce((r, [k, v]) => { r[k] = v && typeof v === 'object' ? transformer(v, keys.filter(s => s.startsWith(k + '.')).map(s => s.split('.').slice(1).join('.'))) : keys.includes(k) ? (v || '') + 1: v; return r; }, {}); } const keys = ['a', 'b.c', 'cde'] object = { a: 'value', b: { c: 'value' }, c: { d: { e: 'value' } }, e: { f: { g: { h : 'value' } } } }; console.log(transformer(object, keys));
 .as-console-wrapper { max-height: 100% !important; top: 0; }

看起来您只想将新值应用于一组范围字段。

您可以遍历所需的范围字段并为它们设置一个新值。 以下问题的答案: 将点表示法中的 JavaScript 字符串转换为对象引用非常适合此问题集。

警告

如果您需要深度复制或克隆对象,您可以对其进行序列化-反序列化:

function cloneObject(obj) {
  return JSON.parse(JSON.stringify(obj));
}

普通分配处理深副本:

function cloneObject(obj) {
  return Object.assign({}, obj);
}

 const array = ['a', 'b.c', 'cde', 'efgh']; const sample = { 'a': 'value', 'b': { 'c': 'value' }, 'c': { 'd': { 'e': 'value' } }, 'e': { 'f': { 'g': { 'h': 'value' } } } }; const newSample = setValueForKeys(cloneObject(sample), array, 'someValue'); console.log('Updated:', newSample); console.log('Original:', sample); function setValueForKeys(source, keys, value) { keys.forEach((key) => index(source, key, value)); return source; } function cloneObject(obj) { return JSON.parse(JSON.stringify(obj)); } // See: https://stackoverflow.com/a/6394168/1762224 function index(obj, is, value) { if (typeof is == 'string') return index(obj, is.split('.'), value); else if (is.length == 1 && value !== undefined) return obj[is[0]] = value; else if (is.length == 0) return obj; else return index(obj[is[0]], is.slice(1), value); } function multiIndex(obj, is) { return is.length ? multiIndex(obj[is[0]], is.slice(1)) : obj; } function pathIndex(obj, is) { return multiIndex(obj, is.split('.')) }
 .as-console-wrapper { top: 0; max-height: 100% !important; }

您可以使用forEach循环来循环数组中的每个元素,然后split每个路径split为数组,然后在该路径数组上使用reduce方法来更新每个嵌套属性。

 const array = ['a', 'b.c', 'cde'] const sample = {"a":"value","b":{"c":"value"},"c":{"d":{"e":"value"}},"e":{"f":{"g":{"h":"value"}}}} function update(array, sample) { array.forEach(c => { c.split('.').reduce((r, e, i, a) => { if (!a[i + 1]) r[e] = r[e] + 1 else return r[e] || {} }, sample) }) } update(array, sample); console.log(sample)

暂无
暂无

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

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