Как проверить, существует ли значение в массиве в массиве объектов?

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть объект, в котором расширенная адресная информация (название улицы, почтовый индекс, номер дома и т.д.). Мне нужно проверить наличие улицы, дома, и если они не существуют, отобразить ошибку. Массив находится ниже:

 const obj = {
    "address_components": [
      {
        "long_name": "10",
        "short_name": "100",
        "types": [
          "street_number"
        ]
      },
      {
        "long_name": "Engelsa street",
        "short_name": "Engelsa street",
        "types": [
          "route"
        ]
      },
      {
        "long_name": "Saint-Petersburg",
        "short_name": "SPB",
        "types": [
          "locality",
          "political"
        ]
      },
      {
        "long_name": "Russia",
        "short_name": "RU",
        "types": [
          "country",
          "political"
        ]
      },
      {
        "long_name": "194017",
        "short_name": "194017",
        "types": [
          "postal_code"
        ]
      }
    ],
    "formatted_address": "Engelsa street, 100, Saint-Petersburg, Russia, 194017",
  } 
 

Комментарии:

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

2. @NinaScholz codesandbox.io/s/strange-roentgen-nvi93?file=/src/App.js

3. пожалуйста, добавьте все, что у вас есть, к вопросу.

4. Ваш вопрос нуждается в доработке … есть объект, в котором расширенная адресная информация неясна

5. Я не уверен на 100%, что вы пытаетесь проверить, но что-то вроде obj.address_components.filter(a => a.types.includes("street_number")) должно работать

Ответ №1:

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

 obj.address_components.some(({ types }) =>
  types.every((type) => [/* list of keys */].includes(type))
);
 
 const obj = {
    address_components: [
      {
        long_name: "10",
        short_name: "100",
        types: ["street_number"]
      },
      {
        long_name: "Engelsa street",
        short_name: "Engelsa street",
        types: ["route"]
      },
      {
        long_name: "Saint-Petersburg",
        short_name: "SPB",
        types: ["locality", "political"]
      },
      {
        long_name: "Russia",
        short_name: "RU",
        types: ["country", "political"]
      },
      {
        long_name: "194017",
        short_name: "194017",
        types: ["postal_code"]
      }
    ],
    formatted_address: "Engelsa street, 100, Saint-Petersburg, Russia, 194017"
  };

const res = obj.address_components.some(({ types }) => types.every(type => ['country', 'locality'].includes(type)));
const res2 = obj.address_components.some(({ types }) => types.every(type => ['country', 'political'].includes(type)));

console.log("'country', 'locality'", res);
console.log("'country', 'political'", res2); 

Если вы хотите выполнить поиск, чтобы каждый ключевой термин включался в какой-либо элемент, тогда используйте:

 [/* list of keys */].every((key) =>
  obj.address_components.some(({ types }) => types.includes(key))
);
 
 const obj = {
  address_components: [
    {
      long_name: "10",
      short_name: "100",
      types: ["street_number"]
    },
    {
      long_name: "Engelsa street",
      short_name: "Engelsa street",
      types: ["route"]
    },
    {
      long_name: "Saint-Petersburg",
      short_name: "SPB",
      types: ["locality", "political"]
    },
    {
      long_name: "Russia",
      short_name: "RU",
      types: ["country", "political"]
    },
    {
      long_name: "194017",
      short_name: "194017",
      types: ["postal_code"]
    }
  ],
  formatted_address: "Engelsa street, 100, Saint-Petersburg, Russia, 194017"
};

const res = ["country", "locality"].every((key) =>
  obj.address_components.some(({ types }) => types.includes(key))
);

console.log("'country', 'locality'", res);
console.log("'country', 'locality', 'city'", ["country", "locality", "city"].every((key) =>
  obj.address_components.some(({ types }) => types.includes(key))
)); 

Комментарии:

1. Спасибо! Другой более короткий вариант obj.address_components.some((a) => a.types.includes("street_number"))

Ответ №2:

Вы могли бы создать функцию, в которой вы передаете требуемые значения, а затем сводите типы к одному массиву. Оттуда вы перебираете требуемые значения, чтобы убедиться, что они соответствуют фактическим значениям:

 const obj = {
  "address_components": [{
      "long_name": "10",
      "short_name": "100",
      "types": [
        "street_number"
      ]
    },
    {
      "long_name": "Engelsa street",
      "short_name": "Engelsa street",
      "types": [
        "route"
      ]
    },
    {
      "long_name": "Saint-Petersburg",
      "short_name": "SPB",
      "types": [
        "locality",
        "political"
      ]
    },
    {
      "long_name": "Russia",
      "short_name": "RU",
      "types": [
        "country",
        "political"
      ]
    },
    {
      "long_name": "194017",
      "short_name": "194017",
      "types": [
        "postal_code"
      ]
    }
  ],
  "formatted_address": "Engelsa street, 100, Saint-Petersburg, Russia, 194017",
};

function isValidAddress(obj, requiredFields) {
  // reduce to array of types ['street_number', 'political', ...etc]
  const actualFields = obj.address_components.reduce((acc, { types }) => {
    acc.push(...types);
    return acc;
  }, []);

  let valid = true;
  // loop through the smaller requiredFields to see if its included in the actual
  requiredFields.forEach((field) => {
    valid = valid amp;amp; actualFields.includes(field);
  });
  
  return valid;
}

const requiredFields = ['street_number', 'route'];


console.log(isValidAddress(obj, requiredFields));