Lodash set every element of an array - javascript

Is there a way to use the string notation in the _.set method to match all items in a nested array?
(e.g. hopefully similar to MongoDB's positional all operator)
const doc = {
nested: [{a: 1}, {a: 2}, {a: 3}]
}
_.set(doc, "nested.$[].a", 5)
// console.log(doc)
// {
// nested: [{a : 5}, {a: 5}, {a: 5}]
// }

No, you can't set every element in a nested array with the .set() method, but you can do this instead:
const doc = {
nested: [{a: 1}, {a: 2}, {a: 3}]
}
// Your attempt.
// _.set(doc, "nested.$[].a", 5)
// Just use a .map() with .assign() instead.
const doc2 = _.assign({}, doc, {
nested: _.map(doc.nested, (obj) => _.assign({}, obj, { a: 5 }))
});
console.log(doc2)
// {
// nested: [{a : 5}, {a: 5}, {a: 5}]
// }
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>

Related

Merge each value in an array to each value in another array - Javascript

I have two arrays
let arr1 = [{a: 1, b: 2}, {a: 3, b: 4}]
let arr2 = [{c: 5}, {c: 6}]
I am trying to create a new array such that each value in arr1 is mapped to each value in arr2. Something like this,
[1-2-5, 1-2-6, 3-4-5, 3-4,6]
I know that this can be done using two for loops. One to loop on arr1 and a nested for loop that loops over arr2. But I am looking for a cheap and efficient method to do it. Any help would be much appreciated! Thanks in advance. Cheers!
You could use map() to achieve this.
let arr1 = [{a: 1, b: 2}, {a: 3, b: 4}]
let arr2 = [{c: 5}, {c: 6}]
const result = arr1.flatMap((x) => {
return arr2.map((y) => `${x.a}-${x.b}-${y.c}`);
});
console.log(result);
Because you can't use - in a number, storing the values in separate arrays would be an option.
let arr1 = [{a: 1, b: 2}, {a: 3, b: 4}]
let arr2 = [{c: 5}, {c: 6}]
const result = arr1.flatMap((x) => {
return arr2.map((y) => [x.a, x.b, y.c]);
});
console.log(result);

get list of object from array of objects using javascript

It is a simple javascript problem and i am unable to get my head through it
const jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
]
let result = jsObjects.find(obj => {
return obj.b === 6
})
console.log(result)
i just want to console the entire list of 'b' rather than find a single variable 'b' which holds value 6
is there any way to do that
You can use Array.filter() instead of Array.find()
const jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
]
let result = jsObjects.filter(obj => obj.b === 6)
console.log(result)
UPDATE
If you want to take only one property, then you can use Array.map()
const jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
]
let result = jsObjects.map(obj => obj.b)
console.log(result);
If you still want them as objects in an array, you can update Harun's code like this:
let myBs = [];
let result = jsObjects.map(obj => myBs.push({b: obj.b}));
console.log(myBs);```

Sort null values to last in Array of Objects

I have an array of objects as follows:
c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}]
I want to kind-of sort them by the objects having values first then objects with null.
What I tried is:
c.sort(function(b) { return b.a ? -1 : 1 })
OUTPUT
[{a: 2}, {a: 50}, {a: 1}, {a: 12}, {a: null}, {a: null}]
EXPECTED OUTPUT
[{a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}, {a: null}]
How can I achieve this?
This will put nulls and other falsy values to the end of the list:
c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
c.sort((x, y) => !!y.a - !!x.a);
console.log(c);
However, since you don't really sort anything, you can just split the list into two parts an rejoin them:
c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
r = [
...c.filter(x => x.a !== null),
...c.filter(x => x.a === null)
]
console.log(r)
This also doesn't rely on the sort function being stable.
You could test the value. If null, then take the delta of the comparison.
var c = [{ a: null }, { a: 12 }, { a: 1 }, { a: 50 }, { a: 2 }, { a: null }];
c.sort(function (a, b) {
return (a.a === null) - (b.a === null);
});
console.log(c);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For a stable sort, you could use sorting with map and use the indices as second sort option.
// the array to be sorted
var list = [{ a: null }, { a: 12 }, { a: 1 }, { a: 50 }, { a: 2 }, { a: null }];
// temporary array holds objects with position and sort-value
var mapped = list.map(function(el, i) {
return { index: i, value: el.a === null};
});
// sorting the mapped array containing the reduced values
mapped.sort(function(a, b) {
return a.value - b.value || a.index - b.index;
});
// container for the resulting order
var result = mapped.map(function(el){
return list[el.index];
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
let result = [...c.filter(_=>_["a"]!==null),...c.filter(_=>_["a"]===null)];
console.log(result);
Try with return !a.a - !b.a .valid object goes first
var c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
c.sort(function (a, b) {
return !a.a - !b.a
});
console.log(c);
That way ?
c=[{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
c.sort(function(a,b){ return a.a===null ? 1:-1 })
console.log(c);
Edited
var c = [{
a: null
}, {
a: 12
}, {
a: 1
}, {
a: 50
}, {
a: 2
}, {
a: null
}];
c.sort(function(a, b) {
return (a.a !== null) ? 0 : 1;
});
console.log(c);
Returning 0 in the sort function will keep the order as it is.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
It is not perfect but still works,cheers!
var c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}]
c.sort(function(object1,object2){
if(object1.a === null && object2.a !== null){return 1}
if([object1.a,object2.a].every((a)=>a === null) ||
[object1.a,object2.a].every((a)=>a !== null)
){return 0}
if(object1.a !== null && object2.a === null){return -1}
})
console.log(c);
Here's a case of sorting a Date with null value at the end if exists:
userSortList = users.sort((a, b) => {
if (b.lastConnectionDate === null || a.lastConnectionDate) {
return -1
} else {
return (
new Date(b.lastConnectionDate) - new Date(a.lastConnectionDate)
)
}
})

What is the suitable data structure or an algorithm to find and remove items from the array

I have an array like this:
const numbers = [{p: 1}, {p: 2}, {p: 3}, {p: 2}];
Now I need to write a function that takes the number, finds the items by that number, returns them and removes them from the array number. I have a very basic implementation of it:
function f(n) {
const filtered = numbers.filter((v) => {
return v.p === n;
});
filtered.forEach((v) => {
const index = numbers.indexOf(v);
numbers.splice(index, 1);
});
return filtered;
}
console.log(f(1)); // [{p: 1}]
console.log(f(2)); // [{p: 2}, {p: 2}]
console.log(numbers); // [{p: 3}]
But I'm wondering if it can be improved with reduce or something else or possibly if there's a data structure instead of an array that supports such logic?
Thanks
Do it with reduceRight starting from the last value in the array, then the splice would be safe:
const numbers = [{p: 1}, {p: 2}, {p: 3}, {p: 2}];
const f = val => numbers.reduceRight((arr, n, i) => {
if (n.p === val) {
numbers.splice(i, 1);
arr.push(n);
}
return arr;
}, []);
console.log(f(1)); // [{p: 1}]
console.log(f(2)); // [{p: 2}, {p: 2}]
console.log('num', numbers); // [{p: 3}]

What's the fastest way to remove an object from an array that has a specific property?

How can I remove:
var arr = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8}];
the object in the array with b set to 2?
arr = arr.filter(function( a ) {
return a.b !== 2;
});
This will only work for IE9+
I think the fastest way to do that would be a for loop, correct me if I'm wrong...
var arr = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8}];
for(var i=0; i<arr.length; i++) {
if(arr[i].b==2) { arr.splice(i,1); }
}
According to jsperf the fastest way to delete an array element is to use delete array[index]. Source: http://jsperf.com/object-delete-vs-array-splice-vs-array-delete
A solution could be this: http://jsfiddle.net/no20bv5o/3/
But because of the overhead in the for loop and the second array it is slower as the before mentioned arr.filter() as shown by this jsperf: http://jsperf.com/filter-array-by-element-attribute

Categories

Resources