У меня есть следующий массив объектов, в котором некоторые определенные ключи имеют значение, которое является либо строкой, либо массивом. Я хочу получить ключи со строковыми значениями как есть и удалить «NA» из ключей со значениями массива.
Я пытаюсь добиться того же, выполняя метод .map для массива, проверяя тип значения каждого ключа в объекте данных, если массив, то используйте .filter для удаления значений «NA».
var dataArr = [
{
a: 'foo',
b: [1, 2, "NA", "NA", 3],
c: ["NA", 6]
},
{
a: 'bar',
b: ["NA", "NA", "NA"],
c: []
}
];
dataArr.map(dataObj => {
for (let key in dataObj) {
if (key !== 'a')
dataObj[key] = dataObj[key].filter(val => { if (val != "NA") return val})
}
return dataObj;
});
Приведенный выше блок кода работает, как и ожидалось, но мне нужно лучшее и перспективное решение. Более того, это тоже плохо выглядит.
dataArr[0].map
не получится. Вы используете карту на объекте JS. Объекты не имеют функции карты.
@Shubham, спасибо, что указали, это опечатка. Я редактирую вопрос.
@CertainPerformance Да, я знаю о проблеме мутации, спасибо, что указали. Но мутация здесь не окажет никакого влияния, так как я убираю ненужные значения.
Используйте for...of
для записей объекта. Для каждой записи проверьте, является ли она массивом. Если это фильтр массива, а затем назначьте новый объект. Если нет, назначьте без фильтрации. Это не изменит исходный массив.
const dataArr = [{"a":"foo","b":[1,2,"NA","NA",3],"c":["NA",6]},{"a":"bar","b":["NA","NA","NA"],"c":[]}]
const result = dataArr.map(dataObj => {
const filterObject = {};
for (const [key, val] of Object.entries(dataObj)) {
filterObject[key] = Array.isArray(val) ?
dataObj[key].filter(val => val != 'NA')
:
val;
}
return filterObject;
});
console.info(result);
Вы можете сделать это, используя вложенные map()
и filter()
map()
на основном массиве.Object.entries()
map()
для записей каждого объекта.Array.isArray
равно false
, в противном случае верните отфильтрованное значение массива.Object.fromEntries()
, чтобы создать объект.var dataArr = [
{
a: 'foo',
b: [1, 2, "NA", "NA", 3],
c: ["NA", 6]
},
{
a: 'bar',
b: ["NA", "NA", "NA"],
c: []
}
];
const res = dataArr.map(x =>
Object.fromEntries(
Object.entries(x)
.map(([k,v]) =>
[k,Array.isArray(v) ? v.filter(b => b !== "NA") : v])
)
)
console.info(res)
Спасибо за ответ, но я не думаю, что это решает проблему временной сложности.
@SibasishMohanty Вы ничего не упомянули о временной сложности в вопросе. В чем проблема с временной сложностью?
Просто интересно, смогу ли я добиться лучшей временной сложности, поскольку количество ключей находится в диапазоне тысяч для каждого объекта.
Если вы просто хотите обновить исходный массив, вы можете прокрутить массив, используя forEach
. Затем переберите ключи каждого объекта, используя for...in
, и проверьте, является ли он массивом, используя Array.isArray()
. Обновите свойство после фильтрация из значения NA
const dataArr = [{a:'foo',b:[1,2,"NA","NA",3],c:["NA",6]},{a:'bar',b:["NA","NA","NA"],c:[]}];
dataArr.forEach(o => {
for (const key in o) {
if (Array.isArray(o[key]))
o[key] = o[key].filter(s => s !== "NA")
}
})
console.info(dataArr)
Если вы хотите получить новый массив без изменения исходных объектов, вы можете использовать map
следующим образом:
const dataArr = [{a:'foo',b:[1,2,"NA","NA",3],c:["NA",6]},{a:'bar',b:["NA","NA","NA"],c:[]}];
const newArray = dataArr.map(o => {
const newObj = {};
for (const key in o) {
if (Array.isArray(o[key]))
newObj[key] = o[key].filter(s => s !== "NA")
else
newObj[key] = o[key]
}
return newObj;
})
console.info(newArray)
const dataArr = [{
a: 'foo',
b: [1, 2, "NA", "NA", 3],
c: ["NA", 6]
},
{
a: 'bar',
b: ["NA", "NA", "NA"],
c: []
}
];
const res = dataArr.map((obj) => {
for(let i in obj){
if (Array.isArray(obj[i])){
obj[i] = obj[i].filter(el=>el!= = "NA")
}
}
return obj;
});
console.info('@>res', res)
Спасибо за ответ, но количество ключей в моем объекте слишком велико, чтобы проверять все их значения по отдельности.
Я предполагаю, что это будет лучший рефакторинг кода, пожалуйста, предоставьте также желаемый результат:
dataArr.forEach(object=>{
for (let value in object){
let isArr = Object.prototype.toString.call(data) == '[object Array]';
isArr? object[value] = object[value].filter(val => {return val != "NA"}):null}
})
typeof
массив тоже "object"
.
Я отредактировал решение, пожалуйста, проверьте его, ссылка на stackoverflow.com/questions/12996871/…
Ваш текущий код мутирующий оригинальный
dataArr
, это действительно желательно?