#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))