JavaScript 从没有指定键的嵌套数组返回
Posted
技术标签:
【中文标题】JavaScript 从没有指定键的嵌套数组返回【英文标题】:JavaScript Return from Nested Array WITHOUT specified Keys 【发布时间】:2022-01-11 07:30:20 【问题描述】:我正在尝试编写一个函数,该函数将从数组中可能嵌套的项中返回一个省略键的对象。我在另一个问题上找到了close answer,但不是我想要的。这是我现在正在修改的代码;
function omit(obj, keys)
let newObj = [];
for (let i of obj)
if (i === keys)
//do nothing
else
//newObj.push[i]; nope?
return newObj;
//return newObj;
编辑: 这是公式和一些示例输入/输出;
var x =
key1: true,
key2: 2,
key3:
nested1: 'javascript'
;
omit(x, ['key2', 'key3']) ==>
key1: true
omit(x, ['nested1']) ==>
key1: true,
key2: 2,
key3: ''
【问题讨论】:
您没有示例输入和输出数据,以及您的代码的一些实现,您不喜欢或不符合您的要求的输出呢? @PeterKA,我更新了我认为你的意思。对不起,对这一切还是很陌生。试图弄清楚在 tl;dr 免责声明之前要扔掉多少细节是必要的,哈哈 请看下面我的解决方案。 【参考方案1】:所以,我对您的问题的解释是,您想要扫描数组中的值并返回没有它们的数组,但是您正在扫描的数组可能包含我们也想要检查的数组。我们不知道数组的格式以及它的深度。我们如何解决这个问题?答案是递归。首先,我们需要了解如何返回一个没有特定键的数组。所以让我们开始吧:
function omitFromArray(array, valuesToOmit)
const newArray = [] // we never reassign, use const
for (const value of array) // use const here as well, technically we make a new variable each iteration of the loop
if (valuesToOmit.indexOf(value) === -1) // if something doesn't exist in an array when we test for an index, it'll return -1
newArray.push(value)
return newArray // we want return to exist *outside* of the for loop so the for loop has a chance to run through all the required iterations;
// in your example, the return keyword is inside the for loop causing it to always give up after the first iteration
const arrayToTest = [1, 2, 3, 4, 5, 6]
const testValuesToOmit = [1, 4, 6]
console.log(omitFromArray(arrayToTest, testValuesToOmit))
// returns [2, 3, 5]
这很好用,但问题是它很浅;它只会扫描数组第一级中的值。为了解决这个问题,我们需要一个递归函数。下面是它的样子:
function omitFromNestedArray(array, valuesToOmit)
function walk(array, valuesToOmit) // this is a modification of the function we wrote before
const newArray = []
for (const value of array)
if (Array.isArray(value)) // except now, we check if the current value happens to be another array
newArray.push(walk(value, valuesToOmit)) // if it is, we actually call the function *inside itself* and return *its* value into our new array
else
if (valuesToOmit.indexOf(value) === -1) // if it's just a value, we can check it like normal
newArray.push(value) // and put it in our array
return newArray // and give it back at the very end
return walk(array, valuesToOmit) // we finally need to call the function at the top level of our array and return that value
const nestedArrayToTest = [1, 2, [3, [4, 5], 6], 7]
const testValuesToOmit = [1, 4, 6]
console.log(omitFromNestedArray(nestedArrayToTest, testValuesToOmit))
// returns [2, [3, [5]], 7]
所以,递归函数的基本概念是函数调用自身。基本的“walk”函数做了我们通常忽略值的事情,但现在它检查我们是否遇到另一个数组;如果是的话,让我们暂停一下,先进入那个并通过它。我们一直这样做,直到我们到达最低级别,然后函数自然地开始循环往复,最终给我们一个新数组。如有任何问题,请追问!
编辑: 为了使代码适应对象而不是数组,我们这样做:
function removeUnwantedKeysFromObject(obj, unwantedKeys)
function walk(obj, unwantedKeys)
for (const key of Object.keys(obj)) // iterating through Object.keys(obj) will return each key in the object
const value = obj[key] // we have to create a variable for the value this way
if (typeof value === 'object') // this is how we check if that value is another object
walk(value, unwantedKeys)
// we can't use else because we also want to delete this whole object if it's inside the keys we want to remove
if (unwantedKeys.indexOf(key) !== -1) // if it's just a value, we can check it like normal
delete obj[key] // this is how you remove a key from an object
walk(obj, unwantedKeys)
let objectToTest = key1: true, key2: 2, key3: nested1: 'JavaScript' ;
removeUnwantedKeysFromObject(objectToTest, ['key2', 'key3'])
console.log(objectToTest)
// returns key1: true
objectToTest = key1: true, key2: 2, key3: nested1: 'JavaScript' ;
removeUnwantedKeysFromObject(objectToTest, ['nested1'])
console.log(objectToTest)
// returns key1: true, key2: 2, key3:
我在这里有一个小警告:此代码编辑原始对象。如果您希望它构造一个新对象,则必须编辑代码以即时构造一个新对象,或使用库(例如 lodash)深度克隆原始对象并返回新对象。否则,这是相同的方法,但适用于对象而不是数组。
【讨论】:
我不得不通读几遍,但它似乎比我开始时更有意义。我敢肯定,更多的实验会让一切顺利。感谢您的帮助! @Alex 检查我所做的编辑,如果您需要更多关于如何使用对象的建议【参考方案2】:下面演示中定义的omit()
函数获取传递的对象的键,过滤掉要排除的键,然后根据剩下的键重建对象。
使用递归omit()
对这些剩余键的所有对象值运行。
const x =
key1: true,
key2: 2,
key3:
nested1: 'JavaScript'
;
const omit = ( obj, keys ) => obj.constructor.name === 'Object' && obj != null ? Object.keys(obj).filter(k => !keys.includes(k)).reduce((a, c) => (
...a,
[c]: omit( obj[c], keys )
), ) : obj;
console.log( omit(x, ['key2']) );
console.log( omit(x, ['nested1']) );
console.log( omit(x, ['nested1','key1']) );
console.log( omit(x, ['key3']) );
【讨论】:
以上是关于JavaScript 从没有指定键的嵌套数组返回的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript:将具有父键的对象数组转换为父/子树(包括没有父的对象)