我有一個函式可以讓我找到第一個找到鍵和值匹配的嵌套物件的路徑。
function getPath(obj, givenKey, givenValue) {
for(var key in obj) {
if(obj[key] && typeof obj[key] === "object") {
var result = getPath(obj[key], givenValue, givenKey);
if(result) {
result.unshift(key)
return result;
}
} else if(obj[key] === givenValue && key === givenKey ) {
return [key];
}
}
}
樣本資料
var myObj = [
{
"name": "needle",
"children": [
{
"name": "group2",
"children": [
{
"name": "item0"
}]
}]
},
{
"name": "item1"
},
{
"name": "needleGroup",
"children": [
{
"name": "needleNestedGroup",
"children": [
{
"name": "item3"
},
{
"name": "needleNestedDeeperGroup",
"children": [
{
"name": "needle"
}]
}]
}]
}];
預期產出
getPath(myObj, "name", "needle"):
[0, "name"]
["2","children","0","children","1","children","0","name"]
但是,我現在有一個多次包含這些鍵值的物件,所以我有多個匹配項。
我怎樣才能把它們全部放在一個陣列中?我當前的功能在找到第一個匹配項后就停止了。事實上,它是遞回的,這讓我覺得事情很復雜
uj5u.com熱心網友回復:
我會把它寫在一個更通用的findAllPaths函式之上,它接受一個謂詞并找到物件中與該謂詞匹配的所有節點的路徑。有了這個,那么findPathsByName就像 一樣簡單(target) => findAllPaths (({name}) => name == target)。
反過來,我建立findAllPaths在pathEntries我一直使用的變體之上。此函式將物件轉換為路徑/值對陣列。有些版本只生成葉節點。這個函式為所有節點生成它,包括根節點(帶有一個空路徑)。這個函式的基本思想是變成這樣的:
{a: 'foo', b: {c: ['bar', 'baz'], f: 'qux'}}
進入這個:
[
[[], {a: 'foo', b: {c: ['bar', 'baz'], f: 'qux'}}],
[['a'], 'foo'],
[['b'], {c: ['bar', 'baz'], f: 'qux'}],
[['b', 'c'], ['bar', 'baz']],
[['b', 'c', 0], 'bar'],
[['b', 'c', 1], 'baz'],
[['b', 'f'], 'qux']
]
其中每個子陣列中的第一項是路徑,第二項是對該路徑值的參考。
這是它可能的樣子:
const pathEntries = (obj) => [
[[], obj],
...Object (obj) === obj
? Object .entries (obj) .flatMap (
([k, x]) => pathEntries (x) .map (
([p, v]) => [[Array .isArray (obj) ? Number (k) : k, ... p], v]
)
)
: []
]
const findAllPaths = (predicate) => (o) =>
[...pathEntries (o)] .filter (([p, v]) => predicate (v, p)) .map (([p]) => p)
const findPathsByName = (target) => findAllPaths (({name}) => name == target)
const myObj = [{name: "needle", children: [{name: "group2", children: [{name: "item0"}]}]}, {name: "item1"}, {name: "needleGroup", children: [{name: "needleNestedGroup", children: [{name: "item3"}, {name: "needleNestedDeeperGroup", children: [{name: "needle"}]}]}]}]
console .log (findPathsByName ('needle') (myObj))
.as-console-wrapper {max-height: 100% !important; top: 0}
該問題要求提供陣列索引的字串值。我更喜歡自己在這里完成的整數值,但是您可以稍微簡化一下函式:
- ([p, v]) => [[Array .isArray (obj) ? Number (k) : k, ... p], v]
([p, v]) => [[k, ... p], v]
uj5u.com熱心網友回復:
您可以將其推送到陣列并繼續迭代,而不是回傳該值。
在函式的末尾,你return是陣列。
function getPath(obj, givenKey, givenValue) {
let matches = [];
for (var key in obj) {
if (obj[key] && typeof obj[key] === "object") {
var result = getPath(obj[key], givenValue, givenKey);
if (result) {
result.unshift(key)
matches.push(...result);
}
} else if (obj[key] === givenValue && key === givenKey) {
matches.push(key);
}
}
return matches;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/326806.html
標籤:javascript 递归
上一篇:scala中的臨時函式以遞回方式連接兩個串列:不使用“concat”
下一篇:物件的扁平樹,同時保留父親和孩子
