【问题标题】:NodeJs comparing two arraysNodeJs比较两个数组
【发布时间】:2021-03-21 09:30:58
【问题描述】:

郑重声明,我是一个相对较新的程序员

我的代码可以运行,但是如果要对许多项目进行排序,它会显得笨重且缓慢

当然,这个节点应用程序不需要很快,即该过程可能需要 5 分钟,这会很好,但我很好奇是否有更好的方法来做到这一点......

我有这个节点应用程序,它正在比较两个数据集...程序的目标如下

  1. 将 csv 文件与在线 api 进行比较
  2. 确保 csv 文件中的所有名称都存在于数组中
  3. 向屏幕抛出错误 (console.log()) 消息而不是完成

现在是代码

const fs = require("fs");
const csv = require("csv-parser");
const fetch = require("node-fetch");

const results = [];

fs.createReadStream("./customers.csv")
  .pipe(csv())
  .on("data", (data) => {
    results.push(data);
  })
  .on("end", () => {
    console.log("Getting Customer Data from Waze...");
    fetch("https://gql.waveapps.com/graphql/public", {
      method: "post",
      headers: {
        //prettier-ignore
        'Authorization': "Bearer MyAuth",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        query: `
          query {
            business(id: "MyBusinessId") {
              customers {
                edges {
                  node {
                    id
                    name
                  }
                }
              }
            }
          }
        `,
      }),
    })
      .then((res) => res.json())
      .then(({ data }) => {
        console.log("Filtering Data...");
        // this maps through the csv file
        results.map((csv) => {
          let array = [];
          name = "";
          data.business.customers.edges.map((customer) => {
            // push the results of the expression (true of false) to an array
            array.push(
              customer.node.name.toLowerCase() === csv.name.toLowerCase()
            );
            // push nonexistent name (if there is one) variable so error handling is clear
            if (customer.node.name.toLowerCase() !== csv.name.toLowerCase()) {
              name = csv.name;
            }
          });
          // if all elements in array are false, that means there is no matching name in the data.business.customers.edges array and error will be true, if there is a true field in the name, return false
          const error = !array.some((el) => {
            if (el) {
              return true;
            }
          });

          if (error) {
            return console.log(
              `Name: ${name} not found in Waze customer list, please check your spelling`
            );
          }
          // send http request here
        });
        console.log("Finished Sending Invoices");
      });
  });

customer.csv 文件

"name","domain","expiration-date"
"bob","yahoo.com","7/2/2020"
"suzie","google.com","12/1/2020"

现在,graphql api 返回的数据看起来像这样......

[
  {
    node: {
      id: 'QnVzaW5lc3M6MzE4NmRmNDQtZDg4Zi00MzgxLTk5ZGEtYTQzMWRmYzhmMDk5O0N1c3RvbWVyOjQ3NTg0Mzc2',
      name: 'NOInvoice'
    }
  },
  {
    node: {
      id: 'QnVzaW5lc3M6MzE4NmRmNDQtZDg4Zi00MzgxLTk5ZGEtYTQzMWRmYzhmMDk5O0N1c3RvbWVyOjQ3NTg0MzU3',
      name: 'Suzie'
    }
  },
  {
    node: {
      id: 'QnVzaW5lc3M6MzE4NmRmNDQtZDg4Zi00MzgxLTk5ZGEtYTQzMWRmYzhmMDk5O0N1c3RvbWVyOjQ3NTgwODkx',
      name: 'Bob'
    }
  }
]

任何帮助将不胜感激

【问题讨论】:

  • 好吧,如果您需要不匹配的属性名称,我看不出有什么办法。您可以 JSON.stringify 两个数组并将它们的结果作为初始检查进行比较,以查看是否需要进一步检查。

标签: javascript node.js arrays filtering


【解决方案1】:

嵌套映射 = O(n*m) 时间复杂度 = 性能不佳

首先从 API 创建名称的哈希图,然后扫描 csv 数组并根据哈希图检查每个名称以查看它是否存在。

使用 hashmap 是提高嵌套循环性能的常用方法。结果将更接近 O(n+m) 时间复杂度,性能显着提高。

  // create hash of valid names from API
  const validNames = data.business.customers.edges.reduce(
    (names, customer) => { 
      names[customer.name] = customer;   /* or = true */
      return names; 
    }, 
    {}
  );

  // see if any of the names in the csv are not valid
  const err = results.reduce((err, csv) => validNames[csv.name] ? err: ++err, 0);
  if (arr > 0) {
    // have invalid names in CSV
  }

  // OR alternatively, find the invalid entries
  const invalid = results.reduce(
    (invalid, csv) => {
      if (!validNames[csv.name]) invalid.push(csv);
      return invalid;
    },
    []
  );

编辑

  // OR shorter version of find the invalid entries
  const invalid = results.filter(csv => !validNames[csv.name]);
  if (invalid.length) {
    // have invalid names in CSV
  }

【讨论】:

  • 非常感谢,我完全忘记了 reduce 方法(太棒了)这不仅更易于阅读和编写,而且速度更快,你是这个人,非常感谢!
【解决方案2】:

我认为您使用了很多您实际上不需要的额外变量,例如 arraynameerror。所以这不是性能优化,而是试图解决代码的笨拙问题。 我指出了一些您可能会考虑的更改。

results.map((csv) => {
   customers_names = data.business.customers.edges.map((edge) => edge.node.name)
   if(!customers_names.some((name) => name === csv.name)) {
     console.log(`Name: ${csv.name} not found in Waze customer list, please check your spelling`)
   }
})

代替:

results.map((csv) => {
  let array = []; <-- (1)
  name = ""; <-- (2)
  data.business.customers.edges.map((customer) => {
    // push the results of the expression (true of false) to an array
    array.push(
      customer.node.name.toLowerCase() === csv.name.toLowerCase()
    );
    // push nonexistent name (if there is one) variable so error handling is clear
    if (customer.node.name.toLowerCase() !== csv.name.toLowerCase()) {
      name = csv.name; <-- (3)
    }
  });
  // if all elements in array are false, that means there is no matching name in the data.business.customers.edges array and error will be true, if there is a true field in the name, return false
  const error = !array.some((el) => {
    if (el) {
      return true;
    }
  }); <-- (4)

  if (error) { <-- (5)
    return console.log(
      `Name: ${name} not found in Waze customer list, please check your spelling`
    );
  }
  // send http request here
});

(1) array 保留 boolean 值,用于确定是否在数据中找到 csv.nameGraphQL 响应)。此array 将在 (4) 上迭代。您实际上不需要通过迭代两个不同的数组来执行两个步骤,因为您实际上可以使用 some 函数并比较名称来找到它。

(2) 中您定义了一个变量 name,在 (3) 中您使用 same 值,即csv.name(它不会改变,因为它根本不依赖于customer)。所以我会完全删除那个变量

(5) 你只关心日志中的csv.name。所以我在较短的版本中就是这样做的

【讨论】:

    猜你喜欢
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2012-12-26
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多