Метод массива фильтр, возвращает целый объект, а надо только несколько полей из объекта если фильтр тру
Есть код, он работает правильно, но проблема в том что если filter тру, то он возвращает целый объект, а надо только пару полей из объекта.
Я сделл кастомный фильтр через forEach, хочу узнать, есть ли элегантное решеие этого вопроса?
Мой кастомный фильтр и метод filter который возвращает целый объект, ниже.
[{
name: {
title: 'Mr',
first: 'Test1',
last: 'Linna1'
},
name: {
title: 'Mr',
first: 'Test2',
last: 'Linna2'
},
name: {
title: 'Mr',
first: 'Test3',
last: 'Linna3'
}
}]
Кастомный
const getLabelUser = (data, state) => {
let labelUser = null;
state.users.forEach(user => {
if (user.name.title === data) {
labelUser = {
name: user.name.title,
};
}
});
if (labelUser) {
return labelUser;
}
};
Первый вариант
const getLabelUser = (data, state) =>
state.users.filter(
user =>
user.name.title === data && {
name: user.name.title,
}
);
Ответы (3 шт):
Я не знаю какую элегантность вы ищите. Во первых, filter возвращает не объект, а массив объектов. К тому же, если вы ожидаете, что будет единственный результат, то лучше использовать методы find или findIndex.
Дальше если вы хотите получить некоторые поля из объекта, можно это сделать так:
const { title: name } = { title: 'Mr', first: 'Test3', last: 'Linna3' };
// name = 'Mr'
Или если в массиве:
const [ { title: name } ] = [ { title: 'Mr', first: 'Test3', last: 'Linna3' }];
// name = 'Mr'
И вообще, в вашем коде, по моему мнению, лучше использовать цикл for-of вместо forEach. В вашем случае это будет нагляднее. Но о вкусах не спорят.
Можно через map:
const [getLabelUser] = (data, state) => state.users.map(user => user.name.title === data && { name: user.name.title, }).filter(Boolean);
Вы не фильтруете, а ищете первое попавшееся под ваше условие. Поэтому наиболее уместно использовать метод Array.prototype.find. Если найден подходящий объект, итерация массива мгновенно прекращается.
Тогда ваш кастомный метод может выглядеть вот так:
function getLabelUser(data, state) {
const user = state.users.find(user => user.name.title === data);
return user && data; // Да, можно вернуть прям data, раз вы ничего специфичного не ищете в этих объектах
}
Можно метод сделать чуть более общим:
// Ищет нужный объект по параметру сравнения в указанном пути и, если найдено, возвращает его
function findAndPluck(arrayOfObjects, lookupData, path) {
// метод безопасно ищет свойство в глубине объекта
const pluck = (object, path) => {
let obj = object;
const propPath = path.split('.').filter(Boolean);
for (const prop of propPath) {
obj = obj[prop];
if (!obj) return;
}
return obj;
};
const found = arrayOfObjects.find(obj => lookupData === pluck(obj, path));
return found && lookupData;
}
// ...
findAndPluck(state.users, 'Семен', 'name.title');