Remove from JS object where key value is an empty array - javascript

I'm trying to remove keys from an object where the values is Array(0). Here's the object:
{fruit: Array(1), dairy: Array(2), vegetables: Array(0)}
This is the desired result:
{fruit: Array(1), dairy: Array(2)}
So far, I've been playing with the delete operator and .filter/.reduce methods.
Any help would be awesome :)

Just iterate over the keys of the object, check if the value for that key is an empty array and if so, delete it:
let obj = {
a: [1],
b: [],
c: 5,
d: false
}
for (const key in obj) { if (Array.isArray(obj[key]) && !obj[key].length) delete obj[key] };
console.log(obj);

The filter/reduce operators are for Arrays not for objects. If you must use the filter/reduce operators, you can try:
const obj = {a: [1], b: [1,2], c: []};
const filtered = Object.keys(obj)
.filter(key => Array.isArray(obj[key]) && obj[key].length != 0)
.reduce((acc, key) => {acc[key] = obj[key]; return acc}, {});
console.log(filtered);

Related

Best way to create an array from an object that has number of copies

From an object like this:
{a:1, b: 2, c: 3}
I would like to turn into
['a', 'b', 'b', 'c', 'c', 'c']
Where the key is the string and the value is the number of copies, order doesn't matter.
What's the best way to do this?
I was thinking about using array.fill but not sure if that's actually easier than just iterating and push.
Edit: Currently this:
const arr = []
_.each(obj, function (v, k) {
_.times(v, function () {
arr.push(k)
})
})
You could flatMap the Object.entries and fill an array of each size.
const obj = { a: 1, b: 2, c: 3 };
const result = Object.entries(obj).flatMap(([k, v]) => Array(v).fill(k));
console.log(result)
or with Lodash
const obj = { a: 1, b: 2, c: 3 };
const arr = _.flatMap(obj, (v,k) => Array(v).fill(k))
console.log(arr);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>
But there's nothing like a simple loop
const obj = { a: 1, b: 2, c: 3 };
const result = []
for (let [k, v] of Object.entries(obj)) {
while (v--) {
result.push(k)
}
}
console.log(result)
I would convert the object into an array of keys using Object.keys and then use a newly created empty results array, then map through the keys.
For each key I would add a fill array to the existing results.
Here's the ES6 solution to that (no extra libraries required)
const obj = { a: 1, b: 2, c: 3 };
let result = []
Object.keys(obj).forEach(key => {
result = [...result, ...new Array(obj[key]).fill(key)]
})
console.log(result)
You can use Object.entries and Array#reduce as follows:
const input = {a:1, b: 2, c: 3};
const output = Object.entries(input).reduce(
(prev, [key,value]) => prev.concat( Array(value).fill(key) ),
[]
);
console.log( output );
Or, using Array#push instead of Array#concat,
const input = {a:1, b: 2, c: 3};
const output = Object.entries(input).reduce(
(prev, [key,value]) => prev.push( ...Array(value).fill(key) ) && prev,
[]
);
console.log( output );
Or, using for loops,
const input = {a:1, b: 2, c: 3};
const output = [],
pairs = Object.entries(input);
for(let i = 0; i < pairs.length; i++) {
const [key, value] = pairs[i];
for(let j = 0; j < value; j++) {
output.push( key );
}
}
console.log( output );

Deleting key to nested object?

In this question I got some excellent answers, but it turned out I had over simplified the problem I am facing.
I have the same object
const obj = {
a: 'A',
b: {
bb: 'BB',
bbb: 'BBB',
},
c: 'C'
};
and I somehow need to end up with
{ a: 'A', bb: 'BB', bbb: 'BBB', c: 'C' }
where there key to the nested object is removed. It doesn't have to be in place. Creating a new object is fine.
Question
Can anyone figure out how to delete the key from the nested object, but still keep the nested object?
You can flatten it recursively:
function flattenObject(obj) {
const ret = {};
for (const [key, val] of Object.entries(obj)) {
if (typeof val === "object") {
Object.assign(ret, flattenObject(val));
} else {
ret[key] = val;
}
}
return ret;
}
Get an array of [key, value] pairs using Object.entries(). Iterate the pairs with Array.flatMap(). If the value is object, call the function with the value. If not return an object of { [key]: value }. Merge to a single object by spreading the array of object into Object.assign().
Use recursion and merge the sub objects by spreading into Object.assign():
const fn = obj => Object.assign({},
...Object.entries(obj)
.flatMap(([k, v]) => typeof(v) === "object" ? fn(v) : { [k]: v })
);
const j = { a: 'A', b: { bb: 'BB', bbb: 'BBB' }, c: 'C' };
const result = fn(j);
console.log(result);
Another option is to work directly with the [key, value] entries (p), and then convert everything to a single object using Object.fromEntries():
const fn = obj =>
Object.entries(obj)
.flatMap(p => typeof(p[1]) === "object" ? fn(p[1]) : [p])
const j = { a: 'A', b: { bb: 'BB', bbb: 'BBB' }, c: 'C' };
const result = Object.fromEntries(fn(j));
console.log(result);

How to set the same value on multiple keys

How is it possible to set the same value on multiple keys? For example I have the following object:
const obj = {
a: 5,
b: 5,
c: 5,
d: 6
}
Is there any easy way for example lets say I have array of [a, b, c] (keys) and to spread them in object and set them as keys with same value. Point is to look more classy for example:
const keys =[a, b, c]
const obj = {
[...keys]: 5
}
I know this would throw error but looking for some shorthand to achieve this
Take the array of keys and map each to an entry of the key and the 5 value:
const keys = ['a', 'b', 'c'];
const obj = {
...Object.fromEntries(
keys.map(key => [key, 5])
),
d: 6
};
console.log(obj);
Something like this works:
const obj = {};
const value = 5;
['a', 'b', 'c'].forEach(key => obj[key] = value);
You can build a zip function which takes an array of keys and a array of values and returns an object where each key/value pair is taken from their respective index:
const zip =
(ks, vs) =>
ks.reduce((o, k, i) =>
(o[k] = vs[i], o), {});
zip(['a', 'b', 'c'], [5, 5, 5]);
//=> {a: 5, b: 5, c: 5}
If you need to generate an array of 5:
Array(3).fill(5);
//=> [5, 5, 5]
Another solution could take a spreading of Object.assign with a spreaded array of objects.
const
keys = ['a', 'b', 'c'],
obj = { ...Object.assign(...keys.map(k => ({ [k]: 5 }))), d: 6 };
console.log(obj);
function(item)
{
return Object.keys(item).reduce((a, b) => ({ ...a, [b]:5 }),{});
}

Convert an array of keys into an object of key-value pairs

I know how to convert this:
const keys = [1, 2, 3];
To this:
[{key: 1, val: "q"}, {key: 2, val: "w"}, {key: 3, val: "e"}]
With a single mapping statement:
keys.map((x, i) => ({key: x, val: "qwe".charAt(i)}));
But I would actually like to get this:
{1: "q", 2: "w", 3: "e"}
Is there a neat way to do this in a single statement similar to the one above?
You can use reduce:
keys.reduce((accumulator, value, index) => { accumulator[index] = "qwe".charAt(index); return accumulator; }, {})
Ahhh, got it:
const objects = Object.assign({}, ...keys.map((x, i) => ({[x]: "qwe".charAt(i)})));
Though I would be happy to hear other suggestions as well as any notes on this one...
You can use reduce, and empty object as the initial value for the accumulator and insert property-value pairs on it:
const keys = [1, 2, 3];
let result = keys.reduce((obj, key, idx) => { obj[key] = 'qwe'[idx]; return obj }, {});
console.log(result)
Here is my solution.
const keys = [1, 2, 3];
const vals = "qwe";
const result = keys.reduce((prev, cur, idx) => ({
...prev,
[cur]: vals[idx]
}), {});

filter the properties of an object based on an array. And get the filtered object

how can i filter the properties of an object based on an array. I have sample snippet below.
var obj = {a: [], b:[], c: [], d:[]}
var arr = ["a", "b"]
Following is my expected output, how can i achieve this
var outupt = {a: [], b:[]}
You could map new objects and create a single object.
var object = { a: [], b: [], c: [], d: [] },
keys = ["a", "b"],
result = Object.assign(...keys.map(k => ({ [k]: object[k] })));
console.log(result);
var obj = {a: [], b:[], c: [], d:[]}
var arr = ["a", "b"]
var output = arr.reduce((result, key) => ({ ...result, [key]: obj[key] }), {});
console.log(output)

Categories

Resources