[英]JavaScript: How to filter array by values nested in object 2 level deep
[英]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.