Как получить значения в массиве объектов, используя другой массив — Javascript

#javascript #arrays

#javascript #массивы

Вопрос:

У меня есть функция, которая взаимодействует с 2 массивами, 1-й массив — это массив объектов, которые содержат мои выпадающие параметры, второй массив — это массив значений. Я пытаюсь отфильтровать 1-й массив, чтобы вернуть то, что соответствует значениям в моем 2-м массиве. Как мне этого добиться?

1-й массив:

 const books = [
    {
        label: "To Kill a Mockingbird",
        value: 1
    },
    {
        label: "1984",
        value: 2
    },
    {
        label: "The Lord of the Rings",
        value: 3
    },
    {
        label: "The Great Gatsby",
        value: 4
    }
]
  

Фрагмент кода ниже:

 const idString = "1,2,3";

function getSelectedOption(idString, books) {
        const ids = idString.split(",");
        const selectedOptions = [];

        ids.map(e => {
            const selected = books.map(options => {
                if (options.value === e){
                    return {
                        label: options.label,
                        value: options.value
                    }
                }
            })
            selectedOptions.push(selected)
        })

        return selectedOptions
    }
  

Результат:

 [
    [undefined, undefined, undefined, undefined],
    [undefined, undefined, undefined, undefined],
    [undefined, undefined, undefined, undefined]
]
  

Ожидаемый результат:

 [
    {
        label: "To Kill a Mockingbird",
        value: 1
    },
    {
        label: "1984",
        value: 2
    },
    {
        label: "The Lord of the Rings",
        value: 3
    }
]
  

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

1. Пожалуйста, посмотрите, что .map() на самом деле делает и почему это неправильный инструмент в данном случае. Если вас не интересует его возвращаемое значение, вам не следует его использовать.

2. Посмотрите, что делает === ( строгое равенство) . e является строкой, options.value числом

3. Как вызвать getSelectedOption функцию? Вы хотите фильтровать объекты, так почему бы не использовать .filter() метод? .map() всегда возвращает значение. Если вы не возвращаете никакого значения, возвращаемый массив будет иметь undefined значение по индексу, для которого вы не вернули никакого значения.

4. books.filter(book => /* do something with book.value and ids that will return true/false */)

Ответ №1:

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

 const idString = "1,2,3";

function getSelectedOption(idString, books) {
  const ids = idString.split(",");
  return ids.map(id => books.find(book => book.value == id)).filter(Boolean)
}
  

Вы также можете отфильтровать массив книг, если вас не волнует порядок или если value он не уникален.

 const idString = "1,2,3";

function getSelectedOption(idString, books) {
  const ids = idString.split(",");
  return books.filter(book => ids.includes(book.value.toString()))
}
  

Пожалуйста, обратите внимание, что это алгоритмы O (n * m), и их не следует использовать с большими наборами данных, однако, если один из массивов относительно мал, вы можете его использовать.

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

1. Две проблемы в вашем коде. 1. массив, возвращаемый ids.map(...) , будет иметь неопределенное значение, если idString содержит какой-либо идентификатор, которого нет в books массиве. Возможно, вы захотите использовать .filter() вместо .map() . 2. book.value является числом, тогда как id является строкой, поэтому book.value === id всегда будет false .

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

3. @GJosh .map() — неправильный метод для использования в вашем случае. используйте .filter() .

4. @Yousaf не могли бы вы пояснить, пожалуйста, почему .map() метод не является правильным методом?

5. .map() метод предназначен для создания нового массива, который содержит преобразованные значения массива, для которого .map() был вызван метод. Он не предназначен для фильтрации элементов массива. Как я упоминал в своем первом комментарии, массив, возвращаемый ids.map(...) будет иметь undefined значение, если idString содержит какой-либо идентификатор, которого нет в массиве books. В первом примере кода в вашем ответе, если idString есть '1,2,3,5' , последним элементом возвращаемого массива будет undefined .

Ответ №2:

 function getSelectedOption(idString, books) {
    const idArray = convertStringToArray(idString)
    return books.filter(item => idString.includes(item.value))
}

function convertStringToArray(string) {
    return string.split(",")
}
  

Ответ №3:

Используя массив filter :

 function getSelectedOption(idString, books) {
  const ids = idString.split(",");
  return books.filter((item) => ids.includes(item.value.toString()));
}

const books = [{
    label: "To Kill a Mockingbird",
    value: 1
  },
  {
    label: "1984",
    value: 2
  },
  {
    label: "The Lord of the Rings",
    value: 3
  },
  {
    label: "The Great Gatsby",
    value: 4
  }
]

const idString = "1,2,3";

getSelectedOption(idString, books);

console.log(getSelectedOption(idString, books));  

Ответ №4:

Некоторые исправления в вашем решении

  • После разделения idString это приведет к массиву строковых значений, поэтому вам нужно преобразовать его в число
  • Вместо использования map для выбора, вы должны использовать find

 const books = [
  {
    label: 'To Kill a Mockingbird',
    value: 1
  },
  {
    label: '1984',
    value: 2
  },
  {
    label: 'The Lord of the Rings',
    value: 3
  },
  {
    label: 'The Great Gatsby',
    value: 4
  }
]

const idString = '1,2,3'

function getSelectedOption(idString, books) {
  const ids = idString.split(',').map(Number)
  const selectedOptions = []

  ids.forEach(e => {
    const selected = books
      .map(options => {
        if (options.value === e) {
          return {
            label: options.label,
            value: options.value
          }
        }
      })
      .filter(options => options !== undefined)
    selectedOptions.push(selected[0])
  })

  return selectedOptions
}

console.log(getSelectedOption(idString, books))