[英]Iterating through JSON using an object
我正在創建一個模板選擇器/輪盤Slack機器人。 目標是向機器人發送消息並傳遞諸如命令行之類的參數,並使其遍歷JSON對象並隨機選擇與條件匹配的模板。 用戶也應該能夠傳遞任何數量的參數。
示例 :我通過此Roulette -s -i
通知機器人,參數是-s
代表側邊欄, -i
代表索引。 因此,機器人程序需要找到同時具有邊欄和索引的模板。
這是我的JSON對象的示例:
{
name: "foo",
index: {
hasIndex: true
},
sidebar: {
hasSidebar: true
}
}
這是我的代碼:
controller.hears(["roulette", "^pattern$"],["direct_message", "direct_mention", "mention"], function(bot,message) {
const data = require('./data.js');
const nodeList = []
const args = message.text.match(/-\w/g);
const obj = {
'-s': '.sidebar.hasSidebar',
'-i': '.index.hasIndex'
}
args.forEach(function(arg) {
var path = obj[arg];
// console.log(path) when passing arguments -s or -i
// the path variable correctly gives me .sidebar.hasSidebar, etc
data.forEach(function(node) {
// console.log(node) Gives me my data set
// console.log(node.path) This is the issue, it returns undefined.
if (node.path === true) {
nodeList.push(node.name)
}
});
});
});
我的問題是,如果node
正確地給我數據集,為什么我不能使用node.path
? 我是否應該能夠添加path
並完成路徑,以便forEach循環通過? 相反,我變得undefined
,我也不明白為什么。
編輯
我已經更新了代碼:
var nodeList = data.filter(function(node) {
return args.every(function(arg) {
return obj[arg](node);
});
});
const obj = {
'-s': function (node) { return node.sidebar.hasSidebar; },
'-i': function (node) { return node.index.hasIndex; },
};
data.forEach(function(node) {
args.forEach(function(arg) {
var pathTester = obj[arg];
if (pathTester(node)) {
nodeList.push(node.name)
}
});
});
1)我是否正確交換了循環?
2)我不太了解nodeList應該如何工作。
當你寫:
if (node.path === true)
...您正在尋找名稱為path
的屬性。 這與您先前聲明的變量path
無關。
使用此語法無法基於點分隔的字符串(例如'.sidebar.hasSidebar'
)查找動態屬性鏈。 您必須調用eval()
才能實現這一點,如下所示:
if (eval('node' + path) === true)
這行得通,但是由於eval
的信譽不好,我建議使用函數而不是字符串的值定義obj
,如下所示:
const obj = {
'-s': function (node) { return node.sidebar.hasSidebar; },
'-i': function (node) { return node.index.hasIndex; },
};
...然后檢索並調用該函數:
args.forEach(function(arg) {
var pathTester = obj[arg];
data.forEach(function(node) {
if (pathTester(node)) {
nodeList.push(node.name);
}
});
});
現在,以上內容回答了這個問題,但是正如您提到的以下內容:
示例:我通過此
Roulette -s -i
向機器人發送消息,參數是-s
代表側邊欄,-i
代表索引。 因此,機器人程序需要找到同時具有邊欄和索引的模板。
...我需要指出的是,即使只有一個條件為真,您當前的代碼也會將節點推入節點列表,並且相同的節點可能會多次推入該列表。
如果只想在所有條件都為真時才添加節點,則交換循環並確保僅當(然后)內部循環對所有參數返回true時才添加節點。
同時,我建議使用every
和filter
函數:
var nodeList = data.filter(function(node) {
return args.every(function(arg) {
return obj[arg](node);
});
});
請注意,這將替換您擁有的forEach
循環。 完整的代碼如下所示:
controller.hears(["roulette", "^pattern$"],["direct_message", "direct_mention", "mention"], function(bot,message) {
const data = require('./data.js');
const args = message.text.match(/-\w/g);
const obj = {
'-s': function (node) { return node.sidebar.hasSidebar; },
'-i': function (node) { return node.index.hasIndex; },
};
var nodeList = data.filter(function(node) {
return args.every(function(arg) {
return obj[arg](node);
});
});
});
filter
和every
以上是走的動力filter
和every
。 沒有這些方法,代碼可能如下所示:
var nodeList = [];
data.forEach(function(node) {
// Check if this node should be added
var addNode = true; // start positive...
args.forEach(function(arg) {
var pathTester = obj[arg];
if (pathTester(node) !== true) {
// if not all paths are true, don't add the node
addNode = false;
}
});
if (addNode) {
nodeList.push(node);
}
});
true
比較的更多信息 當編寫這樣的代碼時:
if (property === true)
... 並且您可以確定該屬性始終為布爾值(如果已定義),那么您可以編寫以下代碼:
if (property)
這是因為if
語句需要計算為布爾值的內容。 但是,如果property已經是一個布爾值,則無需與true
進行比較。 財產有三種可能性。 要么是:
undefined
false
true
當這三個值之一是if
表達式時,只有最后一個true
會使if
條件為true
。 undefined
被認為是虛假的值。
但是,如果屬性也可以是非布爾值,例如數字,字符串或對象,而您只想響應true
的確切值(而不是其他任何值),那么您確實需要像=== true
。 沒有它,非零數值,非空字符串和對象也將通過測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.