NodeJs сравнивает два массива

Для записи я относительно новый программист

У меня есть работающий код, но он кажется неуклюжим и медленным, если ему приходится сортировать множество элементов.

конечно, это приложение узла не должно быть быстрым, т.е. процесс может занять 5 минут, и это будет хорошо, но мне было любопытно, есть ли лучший способ сделать это...

У меня есть это приложение узла, которое сравнивает два набора данных... цели программы следующие

  1. сравните файл csv с онлайн-API
  2. убедитесь, что все имена в файле csv существуют в массиве
  3. выводить сообщение об ошибке (console.info()) на экран вместо завершения

сейчас это код

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.info("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.info("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.info(
              `Name: ${name} not found in Waze customer list, please check your spelling`
            );
          }
          // send http request here
        });
        console.info("Finished Sending Invoices");
      });
  });

файл customer.csv

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

прямо сейчас API-интерфейс graphql возвращает данные, которые выглядят так...

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

любая помощь будет очень признательна

хорошо, если вам нужны имена свойств, которые не совпадают, я не вижу особого способа обойти это. Вы можете JSON.stringify два массива и сравнить их результаты в качестве начальной проверки, просто чтобы увидеть, нужно ли вам дальнейшее изучение.

Tokimon 10.12.2020 00:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
175
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вложенные карты = временная сложность O(n*m) = низкая производительность

Сначала создайте хэш-карту имен из API, затем просмотрите массив csv и проверьте каждое имя по хэш-карте, чтобы увидеть, существует оно или нет.

Использование хэш-карты — распространенный способ повысить производительность вложенных циклов. Результат будет ближе к временной сложности 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
  }

Большое спасибо, я совершенно забыл о методе сокращения (это потрясающе). Это не только легче читать и писать, но и намного быстрее, вы мужчина, и большое спасибо!

Nate Simonsen 11.12.2020 01:56

Я думаю, вы используете много дополнительных переменных, таких как array, name и error, которые вам на самом деле не нужны. Так что это не оптимизация производительности, а попытка решить проблему неуклюжести кода. Я указываю на некоторые изменения, которые вы могли бы рассмотреть.

results.map((csv) => {
   customers_names = data.business.customers.edges.map((edge) => edge.node.name)
   if (!customers_names.some((name) => name === csv.name)) {
     console.info(`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.info(
      `Name: ${name} not found in Waze customer list, please check your spelling`
    );
  }
  // send http request here
});

(1) array хранит значения boolean, которые определяют, был ли найден csv.name в данных (ответ GraphQL). Этот array будет повторяться в (4). На самом деле вам не нужно два шага, перебирая два разных массива, когда вы можете узнать это с помощью функции some и сравнения имен.

В (2) вы определяете переменную name, а в (3) вы продолжаете обновлять эту переменную снова и снова с одним и тем же значением, которое равно csv.name (оно не меняется, потому что вообще не зависит от customer). Поэтому я бы полностью удалил эту переменную

(5) вы заботитесь только о csv.name в журналах. Так что я делаю именно это в более короткой версии

Другие вопросы по теме