I try to write all keys in an array of object whose values are arrays into a new array. Without duplicates. What is the best way in javascript, without libraries like lodash or underscore. I think that my solution is definitely improvable. The single objects and their keys are variable and not always identical. Suggestions wele.
The intended output tom my example should be: [ "stuff", "type", "misc", "something" ]
const items = [{
name: "Joe",
occupied: "no",
mobile: "yes",
treatment: "no",
date: "29-03-2020",
age: "15",
stuff: ["A", "B", "C"],
type: ["1", "2"]
},
{
name: "Jack",
occupied: "yes",
mobile: "no",
treatment: "no",
date: "02-03-2020",
age: "20",
stuff: ["A", "B", "C", "D", "E"],
type: ["8", "6"],
misc: ["otherStuff", "someStuff"]
},
{
name: "Jane",
occupied: "no",
mobile: "yes",
treatment: "yes",
date: "15-02-2020",
age: "28",
stuff: ["C", "D", "E"],
type: ["4", "7"],
something: ["xxx", "ccc"]
}
];
function getKeysWithArrayValues(myArray) {
const result = [];
myArray.forEach(item => Object.entries(item).forEach(itm => itm.filter(Array.isArray).forEach(x => result.push(itm.slice(0, 1)))));
return flatArray(result)
};
function flatArray(array) {
return array.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatArray(val)) : acc.concat(val), []);
};
const ttt = getKeysWithArrayValues(items);
const flat = Array.from(new Set(ttt))
console.log(flat);
I try to write all keys in an array of object whose values are arrays into a new array. Without duplicates. What is the best way in javascript, without libraries like lodash or underscore. I think that my solution is definitely improvable. The single objects and their keys are variable and not always identical. Suggestions wele.
The intended output tom my example should be: [ "stuff", "type", "misc", "something" ]
const items = [{
name: "Joe",
occupied: "no",
mobile: "yes",
treatment: "no",
date: "29-03-2020",
age: "15",
stuff: ["A", "B", "C"],
type: ["1", "2"]
},
{
name: "Jack",
occupied: "yes",
mobile: "no",
treatment: "no",
date: "02-03-2020",
age: "20",
stuff: ["A", "B", "C", "D", "E"],
type: ["8", "6"],
misc: ["otherStuff", "someStuff"]
},
{
name: "Jane",
occupied: "no",
mobile: "yes",
treatment: "yes",
date: "15-02-2020",
age: "28",
stuff: ["C", "D", "E"],
type: ["4", "7"],
something: ["xxx", "ccc"]
}
];
function getKeysWithArrayValues(myArray) {
const result = [];
myArray.forEach(item => Object.entries(item).forEach(itm => itm.filter(Array.isArray).forEach(x => result.push(itm.slice(0, 1)))));
return flatArray(result)
};
function flatArray(array) {
return array.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatArray(val)) : acc.concat(val), []);
};
const ttt = getKeysWithArrayValues(items);
const flat = Array.from(new Set(ttt))
console.log(flat);
Share
Improve this question
edited Mar 29, 2020 at 21:19
Rambone
asked Mar 29, 2020 at 21:03
RamboneRambone
671 silver badge8 bronze badges
2
- 1 please add your solution. – Nina Scholz Commented Mar 29, 2020 at 21:05
- 1 @nina edited code to runable snippet – Rambone Commented Mar 29, 2020 at 21:14
5 Answers
Reset to default 2here is my solution, hope it helps. The algorithm is quite clear and I suppose there is no need to explan much. We just go through an array using reduce method and finally building the new array containing only keys that fit our requirements.
Array.isArray(rec[key]) checks if value is an array.
acc.indexOf(key) < 0 checks if the key has already been included into the resulting array on the one of previos steps.
const arr_ = items
.reduce((acc, rec) => {
return [...acc, ...Object.keys(rec).filter(key => Array.isArray(rec[key]) && acc.indexOf(key) < 0)]
}, [])
You could take a Set
and get unique keys of the objects.
const
items = [{ name: "Joe", occupied: "no", mobile: "yes", treatment: "no", date: "29-03-2020", age: "15", stuff: ["A", "B", "C"], type: ["1", "2"] }, { name: "Jack", occupied: "yes", mobile: "no", treatment: "no", date: "02-03-2020", age: "20", stuff: ["A", "B", "C", "D", "E"], type: ["8", "6"], misc: ["otherStuff", "someStuff"] }, { name: "Jane", occupied: "no", mobile: "yes", treatment: "yes", date: "15-02-2020", age: "28", stuff: ["C", "D", "E"], type: ["4", "7"], something: ["xxx", "ccc"] }],
keys = Array.from(
items.reduce(
(s, o) => Object
.keys(o)
.reduce((t, k) => Array.isArray(o[k]) ? t.add(k) : t, s),
new Set
)
);
console.log(keys);
Use flatMap
to iterate through each object's keys and return a filtered array of keys, on the condition of whether the value at that key is an array:
const items=[{name:"Joe",occupied:"no",mobile:"yes",treatment:"no",date:"29-03-2020",age:"15",stuff:["A","B","C"],type:["1","2"]},{name:"Jack",occupied:"yes",mobile:"no",treatment:"no",date:"02-03-2020",age:"20",stuff:["A","B","C","D","E"],type:["8","6"],misc:["otherStuff","someStuff"]},{name:"Jane",occupied:"no",mobile:"yes",treatment:"yes",date:"15-02-2020",age:"28",stuff:["C","D","E"],type:["4","7"],something:["xxx","ccc"]}];
const keysWithArrays = new Set(
items.flatMap(
item => Object.keys(item).filter(key => Array.isArray(item[key]))
)
);
console.log([...keysWithArrays]);
You can use set and Array.isArray() to check if value is array.
let mySet = new Set(); const items = [{name: "Joe",occupied: "no",mobile: "yes",treatment: "no",date: "29-03-2020",age: "15",stuff: ["A", "B", "C"],type: ["1", "2"]},{name: "Jack",occupied: "yes",mobile: "no",treatment: "no",date: "02-03-2020",age: "20",stuff: ["A", "B", "C", "D", "E"],type: ["8", "6"],misc: ["otherStuff", "someStuff"]
}, {name: "Jane",occupied: "no",mobile: "yes",treatment: "yes",date: "15-02-2020",age: "28",stuff: ["C", "D", "E"],type: ["4", "7"],something: ["xxx", "ccc"]}];
items.forEach((obj)=> Object.keys(obj).forEach( prop=>{if(Array.isArray(obj[prop]))
mySet.add(prop)})); console.log(Array.from(mySet));
.as-console-wrapper { max-height: 100% !important; top: 0; }
One more way with Object.fromEntries
, flatMap
and filter
.
const items = [
{
name: "Joe",
occupied: "no",
mobile: "yes",
treatment: "no",
date: "29-03-2020",
age: "15",
stuff: ["A", "B", "C"],
type: ["1", "2"]
},
{
name: "Jack",
occupied: "yes",
mobile: "no",
treatment: "no",
date: "02-03-2020",
age: "20",
stuff: ["A", "B", "C", "D", "E"],
type: ["8", "6"],
misc: ["otherStuff", "someStuff"]
},
{
name: "Jane",
occupied: "no",
mobile: "yes",
treatment: "yes",
date: "15-02-2020",
age: "28",
stuff: ["C", "D", "E"],
type: ["4", "7"],
something: ["xxx", "ccc"]
}
];
const keys = Object.keys(
Object.fromEntries(
items.flatMap(item =>
Object.entries(item).filter(([, value]) => Array.isArray(value))
)
)
);
console.log(keys);