#javascript #json #object #reduce
Вопрос:
У меня есть объект javascript ниже:
let filters = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
}
И я получил два ввода: 'numbers'
и ['4','5']
Я хочу получить:
{
numbers: {
'is_no_selected': false,
'is_one_selected': false,
'is_two_selected': false,
'is_three_selected': false,
'is_four_selected': true,
'is_five_selected': true,
}
}
И когда я ввожу два других ввода: 'words'
и ['please']
Я хочу получить:
{
words: {
'is_please_selected': true,
'is_help_selected': false,
'is_me_selected': false,
}
}
Как это сделать с помощью reduce()
?
Комментарии:
1. в общем, я думаю, что вы могли бы преобразовать объект в массив, а затем уменьшить
Ответ №1:
Вам нужно получить записи объекта перед использованием reduce
:
let filters = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
}
function fn(obj, filterKey, filters) {
filters = filters.map(x => '' x); // convert all filters to strings (keys are always string)
return Object
.keys(obj)
.filter(x => x === filterKey) // only the selected property
.map(x => obj[x]) // get the object
.map(x => {
return Object.entries(x).reduce((out, curr) => {
const [key, val] = curr;
out[val] = filters.includes(key);
return out;
}, {})
});
}
console.log(fn(filters, 'numbers', [0]))
Ответ №2:
Для меня проще всего объединить входные данные в объект с одинаковыми номерами и ключами слов.
Затем повторите Object.entries()
и сопоставьте ключи чисел/слов между объектами ввода и фильтра
let filters={numbers:{0:"is_no_selected",1:"is_one_selected",2:"is_two_selected",3:"is_three_selected",4:"is_four_selected",5:"is_five_selected"},words:{please:"is_please_selected",help:"is_help_selected",me:"is_me_selected"}};
const inputs = {
numbers: ['4', '5'],
words: ['please'],
};
const res = {};
Object.entries(filters).forEach(([key,o])=>{
const fil = res[key] = {};
Object.entries(o).forEach(([k,v]) => fil[v] = inputs[key].includes(k));
})
console.log(res)
Ответ №3:
Держи. Не так, как я бы это сделал, но если вам нужно использовать reduce, вы можете сделать это так.
let filters = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
}
var numbers = filter(filters, 'numbers', ['4', '5']);
var words = filter(filters, 'words', ['please']);
console.log(numbers);
console.log(words);
function filter(filter_obj, key, input) {
return {
[key]: Object.keys(filters[key]).reduce((a, c) => {
a[filters[key][c]] = input.includes(c)
return a;
}, {})
}
}
Ответ №4:
Использование двух reduce()
для фильтрации внутреннего объекта и внешнего объекта.
/* input is the data and filtering key and value list */
function filter (data, key, vals) {
// inner filter
const filterValues = (obj, values) => Object.keys(obj).reduce((accum, ele) => {
accum[obj[ele]] = values.includes(ele);
return accum;
}, {});
// outer filter
const filteredKey = Object.keys(data).reduce((accum, ele) => {
if (ele === key)
accum[key] = data[key];
return accum;
}, {});
// call outer filter first then pass it to inner filter
return {
[key]: filterValues(filteredKey[key], vals)
};
}
Назовите его с данными, которые вы дали в первом аргументе, как:
console.log(filter(data, 'numbers', ['4', '5']));
console.log(filter(data, 'words', ['please']));
Вот полный код, который вы можете протестировать и запустить.
const data = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
}
/* input is data and filtering key and value list */
function filter (data, key, vals) {
// inner filter
const filterValues = (obj, values) => Object.keys(obj).reduce((accum, ele) => {
accum[obj[ele]] = values.includes(ele);
return accum;
}, {});
// outer filter
const filteredKey = Object.keys(data).reduce((accum, ele) => {
if (ele === key)
accum[key] = data[key];
return accum;
}, {});
// call outer filter first then pass it to inner filter
return {
[key]: filterValues(filteredKey[key], vals)
};
}
console.log(filter(data, 'numbers', ['4', '5']));
console.log(filter(data, 'words', ['please']));
Ответ №5:
Конечно, очень простой код в одну строку
let filters = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
}
const fn=(f,a)=>({[f]:Object.entries(filters[f]).reduce((r,[k,v])=>(r[v]=a.includes(k),r),{})});
console.log(fn('numbers', ['4','5']))
console.log(fn('words',['please']))
Ответ №6:
Базовое решение:
function filter(all_option, select_key, select_option) {
let ret = {};
let s_f = all_option[select_key];
for (let k in s_f) {
if (select_option.includes(k)) {
ret[s_f[k]] = true;
} else {
ret[s_f[k]] = false;
}
}
return ret;
}
преобразуйте его в уменьшенную версию карты:
function filter(all_option, select_key, select_option) {
let ret = {};
let s_f = all_option[select_key];
Object.keys(s_f).map(k => {
if (select_option.includes(k)) {
ret[s_f[k]] = true;
} else {
ret[s_f[k]] = false;
}
});
return ret;
}
Ответ №7:
таким образом…
const filters =
{ numbers:
{ '0': 'is_no_selected'
, '1': 'is_one_selected'
, '2': 'is_two_selected'
, '3': 'is_three_selected'
, '4': 'is_four_selected'
, '5': 'is_five_selected'
}
, words:
{ please: 'is_please_selected'
, help: 'is_help_selected'
, me: 'is_me_selected'
}
}
const foo = (in1,in2) =>
Object.entries(filters[ in1 ])
.reduce((r,[k,v]) => Object.assign(r,{[v]:in2.includes(k)}), {})
console.log('a;', foo('numbers', ['4','5']) )
console.log('b;', foo('words', ['please']) )
.as-console-wrapper { max-height: 100% !important; top: 0 }
Ответ №8:
Вы можете уменьшить свои numbers
и words
объекты, уменьшив их Object.entries (), который возвращает одну array
из пар собственных перечисляемых свойств объекта [key, value]
.
let filters = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
};
let reduceFilter = function(filters, name, input) {
return Object.entries(filters[name]).reduce((acc, [key, value]) => {
acc[name][value] = input.includes(key);
return acc;
}, {[name]: {}});
};
console.log(reduceFilter(filters, 'numbers', ['4', '5']));
console.log(reduceFilter(filters, 'words', ['please']));
Обратите внимание, что оба выражения функции редуктора используют приведенные выше задания разрушения, чтобы легко разбить [key, value]
пары.
Комментарии:
1. почему свойство жестко закодированного фильтра и две идентичные функции?
2. @Bravo Спасибо вам за конструктивную критику. Я прошу вас еще раз просмотреть мой ответ.
3. теперь это выглядит так же, как половина всех остальных ответов — так что, да, это замечательно
Ответ №9:
Я бы сделал что-то вроде ниже
const process = function (data, key, input) {
const result = Object.keys(data[key])
.reduce((acc, index) => {
const isValid = input.includes(index);
if(isValid)
acc[data[key][index]] = true;
else
acc[data[key][index]] = false;
return acc;
}, {});
return {
[key] : result
}
};
var filters = {
numbers: {
'0': 'is_no_selected',
'1': 'is_one_selected',
'2': 'is_two_selected',
'3': 'is_three_selected',
'4': 'is_four_selected',
'5': 'is_five_selected',
},
words: {
please: 'is_please_selected',
help: 'is_help_selected',
me: 'is_me_selected',
},
};
// client code: process(filters, 'numbers', ['4', '5']));