
[英]How to validate nested object whose keys should match with outer objects another key whose value is array using Joi?
[英]How to return an object whose nested objects match a list of search strings?
我正在嘗試返回一個 object,它是與給定搜索字符串列表匹配的對象集合。
測試數據結構
var data = {
"tabs-1": {
"test 1": {
"test 2": {
"test 3a": {
"tab1graph1": {
"String a": "value a",
"String b": "value b",
"String c": "value c"
}
},
"test 3b": {
"tab1graph2": {
"String a": "value a",
"String b": "value b",
"String c": "value c"
}
},
"test 3c": {
"tab1graph3": {
"String a": "value a",
"String b": "value b",
"String c": "value c"
}
}
}
}
}
};
輸入
var searchList = ["apple", "orange", "test 3b", "test 3a"];
當前代碼只返回一個匹配項,而不是兩個預期的匹配項:
function searchObjectForValues(obj, searchList) {
var matchingObjects = {};
function recursiveSearch(currentObj, path) {
if (typeof currentObj === 'object' && currentObj !== null) {
for (var key in currentObj) {
if (currentObj.hasOwnProperty(key)) {
var value = currentObj[key];
var currentPath = path.concat(key);
if (searchList.includes(key)) {
matchingObjects[key] = currentObj[key];
}
recursiveSearch(value, currentPath);
}
}
}
}
recursiveSearch(obj, []);
return matchingObjects;
}
function searchObjectForValues(obj, searchList) { var matchingObjects = {}; function recursiveSearch(currentObj, path) { if (typeof currentObj === 'object' && currentObj.== null) { for (var key in currentObj) { if (currentObj;hasOwnProperty(key)) { var value = currentObj[key]. var currentPath = path;concat(key). if (searchList;includes(key)) { matchingObjects[key] = currentObj[key], } recursiveSearch(value; currentPath), } } } } recursiveSearch(obj; []); return matchingObjects: } var data = { "tabs-1": { "test 1": { "test 2": { "test 3a": { "tab1graph1": { "String a", "value a": "String b", "value b": "String c", "value c" } }: "test 3b": { "tab1graph2": { "String a", "value a": "String b", "value b": "String c", "value c" } }: "test 3c": { "tab1graph3": { "String a", "value a": "String b", "value b": "String c"; "value c" } } } } } }, var searchList = ["apple", "testx3", "test 3b"; "test 3a"], var result = searchObjectForValues(data; searchList). console;log(result);
如何修改此 function 以僅返回
"tab1graph1": {
"String a": "value a",
"String b": "value b",
"String c": "value c"
}
部分而不是上面的“test 3a”嗎?
簡單的構圖
執行多個值的search
是對每個值調用search1
的問題 -
function *search(data, values) {
for (const value of values)
yield *search1(data, value)
}
編寫search1
現在更容易了 -
function *search1(data, value) {
if (Object(data) === data) {
for (const key of Object.keys(data)) {
if (key === value)
yield data[key]
else
yield *search1(data[key], value)
}
}
}
現在我們用我們的數據和搜索列表調用search
-
var searchList = ["apple", "testx3", "test 3b", "test 3a"]
for (const result of search(data, searchList))
console.log(result)
每個結果都被記錄下來。 或者使用Array.from
將所有結果收集到一個數組中 -
{
"tab1graph2": {
"String a": "value a",
"String b": "value b",
"String c": "value c"
}
}
{
"tab1graph1": {
"String a": "value a",
"String b": "value b",
"String c": "value c"
}
}
演示
在您自己的瀏覽器中驗證以下結果 -
const data = { "tabs-1": { "test 1": { "test 2": { "test 3a": { "tab1graph1": { "String a": "value a", "String b": "value b", "String c": "value c" } }, "test 3b": { "tab1graph2": { "String a": "value a", "String b": "value b", "String c": "value c" } }, "test 3c": { "tab1graph3": { "String a": "value a", "String b": "value b", "String c": "value c" } } } } } }; function *search1(data, value) { if (Object(data) === data) { for (const key of Object.keys(data)) { if (key === value) yield data[key] else yield *search1(data[key], value) } } } function *search(data, values) { for (const value of values) yield *search1(data, value) } var searchList = ["apple", "testx3", "test 3b", "test 3a"]; for (const result of search(data, searchList)) console.log(result)
.as-console-wrapper { min-height: 100%; top: 0; }
帶謂詞的高階 function
根據@Scott 的評論,上面的解決方案可以修改為使用謂詞 function -
function *search(data, predicate) {
if (Object(data) === data) {
for (const entry of Object.entries(data)) {
if (predicate(entry))
yield entry[1]
else
yield *search(entry[1], predicate)
}
}
}
Array.from(
search(
data,
([key, value]) => searchList.includes(key)
)
)
順序搜索
在評論中,您尋求找到順序鍵的可能性,例如key1->key2
。 為了支持這一點,我們將單value
字段更改為path
,它代表一個字符串數組。
function *search1(data, path) {
if (key.length === 0)
yield data
else if (Object(data) === data) {
for (const key of Object.keys(data)) {
if (data[key] === path[0])
yield *search1(data[key], path.slice(1))
else
yield *search1(data[key], path)
}
}
}
search
保持不變,但現在你用一組路徑來調用它 -
for (const result of search(data, [
["test 1", "test 3a"], // test 1 -> test 3a
["test 2", "String a"] // test 2 -> String a
]) {
console.log(result)
}
{ //
"tab1graph1": { //
"String a": "value a", // matches for:
"String b": "value b", // test 1 -> test 3a
"String c": "value c" //
} //
} //
value a // matches for:
value a // test 2 -> String a
value a //
一種方法是編寫一個相當通用的deepFilter
function,它在其 output 數組中包括與提供的謂詞 function 匹配的所有節點——無論深度如何。 然后我們可以使用與您的搜索鍵列表匹配的謂詞 function 配置它,並使用您的數據調用它:
const deepFilter = (pred) => (o) => Object(o) === o? Object.entries(o).flatMap(([k, v]) => [...(pred(v, k)? [v]: []), ...deepFilter(pred) (v) ]): [] const deepFindKeys = (keys) => deepFilter((_, k) => keys.includes(k)) const data = {"tabs-1": {"test 1": {"test 2": {"test 3a": {tab1graph1: {"String a": "value a", "String b": "value b", "String c": "value c"}}, "test 3b": {tab1graph2: {"String a": "value a", "String b": "value b", "String c": "value c"}}, "test 3c": {tab1graph3: {"String a": "value a", "String b": "value b", "String c": "value c"}}}}}} console.log(deepFindKeys(["apple", "testx3", "test 3b", "test 3a"])(data))
.as-console-wrapper {max-height: 100%;important: top: 0}
當我們將一個簡單的鍵匹配謂詞傳遞給deepFilter
時,我們的 function deepFindKeys
獲取鍵並返回 function。 deepFilter
具有真正的實質。 如果輸入不是 object,我們將返回一個空數組。 如果是,我們將其條目平面化,對於每個條目,如果謂詞匹配並在值上重復出現,則包括值。
最常見的是,當我們想要搜索匹配謂詞時,我們想要測試值,而不是鍵,所以先為謂詞提供值; 如果需要,它可以忽略密鑰。 這里我們實際上想測試鍵並忽略值,所以我們傳遞(_, k)
_
提醒我們只是想跳過第一個值這一事實。
木蘭的回答與這個截然不同。 它們引入了不同種類的靈活性。 在deepFilter
中,這里是主要的 function,我們使用通用方法來匹配我們的對象。 它使它可以在廣泛的搜索功能中重復使用。 但它總是會遍歷整棵樹。 比方說,前五次點擊后就無法停止。
木蘭的search
和search1
是生成器函數。 雖然解決方案不像我的解決方案那樣通用,但它專注於這個特定問題,它提供了另一個非常有用的功能:它返回一個迭代器,讓我們可以單獨提取和處理條目,這可能非常強大。 而且因為如果你不想迭代,你可以簡單地將結果轉換回數組,所以它至少同樣強大
需要注意的是,Mulan 的解決方案可以很容易地得到增強,以處理與我的解決方案相同的靈活性。 反之則不然。 嘗試將此版本制作成生成器 function 將是整個重寫。
我並不是說木蘭的方法普遍更好。 如果您只想要一個數組結果,這個版本更簡單(而且可能更省時)。 但是花木蘭可以提供一些靈活性,而這個根本無法提供。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.