Поиск пропущеных значений при переборе массива

110
31 января 2022, 09:50

Есть массив с объектами (deliveryCost - страна и стоимость доставки в страну). Необходимо реализовать вызов функции с запрашиваемой страной: если она (country) есть в массиве - отобразить стоимость доставки (cost). Если её нет, просто отобразить в консоли: "В вашу страну доставка не осуществляется".

Я пробовал через перебор массива (map, filter, find..) - в моей реализации, когда страна не найдена, все равно перебирается весь массив и выводится сообщение столько раз, сколько объектов в массиве. Значит, неверна сама реализация.

Подскажите, где я допускаю ошибку. Спасибо Вам!

const deliveryCost = [ 
  { country: "Китай", cost: 100 }, 
  { country: "Чили", cost: 250 }, 
  { country: "Австралия", cost: 170 }, 
  { country: "Индия", cost: 80 }, 
  { country: "Ямайка", cost: 120 } 
]; 
 
const countryForDelivery = (arr, countryName) => { 
  arr.map(elem => { 
    if (elem.country === countryName) { 
      yesDelivery(elem.country, elem.cost); 
    } else { 
      noDelivery(countryName); 
    } 
  }); 
}; 
 
function yesDelivery(country, cost) { 
  console.log(`Доставка в ${country} будет стоить ${cost} кредитов`); 
} 
 
function noDelivery(country) { 
  console.log(`В ${country} доставка не доступна`); 
} 
 
countryForDelivery(deliveryCost, "Индия"); // есть в списке 
countryForDelivery(deliveryCost, "Исландия"); // нет в списке

Answer 1

Вам map в данном случае не нужен, т.к. он предназначен для создания нового массива на основании существующего (т.е. для каждого элемента вызывается ваша функция, поэтому в консоли и куча сообщений). Вам достаточно с помощью filter/find найти нужный элемент и если он есть выводить одно сообщение, если нет - другое.

const countryForDelivery = (arr, countryName) => {
    const elem = arr.find(elem => elem.country === countryName);
    if (elem) {
        yesDelivery(elem.country, elem.cost);
    } else {
        noDelivery(countryName);
    }
};
Answer 2

Обычно, имеет смысл создать производный Map (или обычный объект) для скоростного доступа по одному из полей, без какого-либо перебора вложенных объектов.
Почему это лучше - потому что объекты это хэш-таблицы. При доступе по ключам, интерпретатор использует только их хэши (а это значительно быстрее, чем любой перебор в юзеркоде, будь то for+if или find).

Объект Map, и внешняя функция (внутренний поиск чуть быстрее):

const deliveryCostData = [ 
  { country: "Китай", cost: 100 }, 
  { country: "Чили", cost: 250 }, 
  { country: "Австралия", cost: 170 }, 
  { country: "Индия", cost: 80 }, 
  { country: "Ямайка", cost: 120 } 
]; 
const deliveryCostMap = deliveryCostData.reduce( 
  (rslt, obj) => rslt.set(obj.country, obj)  
, new Map);  
 
const deliveryFor = country => { 
  const entry = deliveryCostMap.get(country);  
  if (!entry || (typeof entry.cost === 'undefined')) 
    console.log(`В ${country} доставка не доступна`); 
  else 
    console.log(`Доставка в ${country} будет стоить ${entry.cost} кредитов`); 
};  
 
deliveryFor('Индия'); // есть в списке 
deliveryFor('Исландия'); // нет в списке

Обычный объект, с методом (удобнее благодаря инкапсуляции):

const deliveryCostData = [ 
  { country: "Китай", cost: 100 }, 
  { country: "Чили", cost: 250 }, 
  { country: "Австралия", cost: 170 }, 
  { country: "Индия", cost: 80 }, 
  { country: "Ямайка", cost: 120 } 
]; 
const delivery = deliveryCostData.reduce( 
  (rslt, obj) => Object.assign(rslt, { [obj.country]: obj })  
, { 
    forCountry(country) { 
      if (this.hasOwnProperty(country)) 
        console.log(`Доставка в ${country} будет стоить ${this[country].cost} кредитов`);  
      else 
        console.log(`В ${country} доставка не доступна`); 
    },  
  } 
);  
 
delivery.forCountry('Индия'); // есть в списке 
delivery.forCountry('Исландия'); // нет в списке

В обоих случаях имеет смысл присваивать в качестве значения весь объект, а не только его поле cost. Потому что:

  • Эффективно по ресурсам (1. объекты присваиваются по ссылке, доп. память не выделяется; 2. интерпретатору не нужно запоминать дублирующую схему объектов, и выполнять сопутствующие проверки схем на каждой итерации построения словаря)

  • Как следствие передачи по ссылке, получаем взаимосвязь данных в объектах и возможность упрощения логики (изменение cost или добавление новых свойств в объекты deliveryCostData, автоматически отразится на объектах в словаре - при таких операциях, нет нужды его перестраивать)

  • Значительно упрощается поддержка кода (если в будущем добавятся еще "постоянные" поля помимо cost, код не нужно будет переписывать - достаточно будет дополнить его новыми хелперами/методами).

READ ALSO
Как сделать стартовую страницу на динамической дирректории?

Как сделать стартовую страницу на динамической дирректории?

Всем приветВ проекте стоит задача, в котором стартовый URL должен начинаться с абривеатуры языка

73
SyntaxError: Unexpected token 'export'

SyntaxError: Unexpected token 'export'

подскажите как решить проблему с тестами мой основной js (activeBtnClickjs):

137