Для записи я относительно новый программист
У меня есть работающий код, но он кажется неуклюжим и медленным, если ему приходится сортировать множество элементов.
конечно, это приложение узла не должно быть быстрым, т.е. процесс может занять 5 минут, и это будет хорошо, но мне было любопытно, есть ли лучший способ сделать это...
У меня есть это приложение узла, которое сравнивает два набора данных... цели программы следующие
сейчас это код
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'
}
}
]
любая помощь будет очень признательна
Вложенные карты = временная сложность 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
}
Большое спасибо, я совершенно забыл о методе сокращения (это потрясающе). Это не только легче читать и писать, но и намного быстрее, вы мужчина, и большое спасибо!
Я думаю, вы используете много дополнительных переменных, таких как 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
в журналах. Так что я делаю именно это в более короткой версии
хорошо, если вам нужны имена свойств, которые не совпадают, я не вижу особого способа обойти это. Вы можете JSON.stringify два массива и сравнить их результаты в качестве начальной проверки, просто чтобы увидеть, нужно ли вам дальнейшее изучение.