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

问题描述 投票:0回答:3

我有一个数组和一个示例对象,如下所示:

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

样本

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

然后,我想根据数组中的细节修改样本。结果应如下所示:

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

我正在考虑遍历数组并计算每个元素的长度。但是,它的效率不如阵列和样品的水平提高。有没有更好的算法?

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

const sample = {
  '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)

谢谢,

javascript algorithm
3个回答
0
投票

似乎您只想将新值应用于一组范围域。

您可以在所需的作用域上循环,并为其设置一个新值。以下问题的答案:Convert JavaScript string in dot notation into an object reference对于此问题集非常有效。

const array = ['a', 'c.d.e', 'e.f.g.h'];

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

const newSample = setValueForKeys(sample, array, 'someValue');

console.log(newSample);

function setValueForKeys(source, keys, value) {
  keys.forEach((key) => index(source, key, value));
  return source;
}

// 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; }

0
投票

您可以使用forEach循环执行此操作,以循环数组中的每个元素,然后循环到split数组的每个路径,然后对该路径数组使用reduce方法来更新每个嵌套的属性。

const array = ['a', 'b.c', 'c.d.e']
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)

0
投票

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

const 
    keys = ['a', 'b.c', 'c.d.e']
    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; }
© www.soinside.com 2019 - 2024. All rights reserved.