簡體   English   中英

使用對象遍歷JSON

[英]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時才添加節點。

同時,我建議使用everyfilter函數:

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);
        });
    });
});

更多關於filterevery

以上是走的動力filterevery 沒有這些方法,代碼可能如下所示:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM