Adding Ids to an Array - javascript

I tried adding an id property to the objects in my sorted output, but all I'm doing is not working. Is there anything I should have done?
My Code Below:
var arr = [{ one: 2 },
{ two: 3 },
{ three: 4 },
{ four: 1 }];
const arr1 = arr.reduce((a,b) => ({...a,...b}), {})
var sorting = Object.entries(arr1).sort((a, b) => b[1] - a[1]);
console.log(sorting);
Expected Result:
var arr1 = [{ name: "three", value: 4, id: 1 },
{ name: "two", value: 3, id: 2 },
{ name: "one", value: 2, id: 3 },
{ name: "four", value: 1, id: 4 }];

Object.assign can do what you did with reduce, and I would not call that result arr1, as it is not an array, but a plain object.
In the final step it helps to use destructuring and map to an object literal with shortcut notation:
const arr = [{one: 2}, {two: 3}, {three: 4}, {four: 1}];
const obj = Object.assign({}, ...arr);
const sorted = Object.entries(obj).sort((a, b) => b[1] - a[1]);
const result = sorted.map(([text, value], i) => ({ text, value, id: i+1}));
console.log(result);

/*If i console.log(sorting) I have
[['three', 4 ], ['two', 3 ], ['one', 2 ], ['four', 1 ],]
Without Ids but i want something like the expected result below*/
/* Expected Result
[['three', 4 id = 1], ['two', 3 id = 2], ['one', 2 id = 3], ['four', 1 id = 4],]
*/
UPD, sorry, didn't get it right first time
var empty = [];
var arr = [{
one: 2
}, {
two: 3
}, {
three: 4
},{
four: 1
}];
const arr1 = arr.reduce((a,b) => ({...a,...b}), {})
const sorting = Object.entries(arr1).sort((a, b) => b[1] - a[1]);
// Add indexes starting from 1
const indexed = sorting.map((a,b) => a.push({ "id": b+1 }));
console.log(sorting);

I am going to go with a guess here that you want a descending sorted array of objects, adding an id property based on the original index + 1 of each original object. We can do that by reference to the object key (first property 0) when we sort after we add the ids to the original objects in a new array.
// not used in the question/issue
//var empty = [];
var arr = [{
one: 2
}, {
two: 3
}, {
three: 4
}, {
four: 1
}];
const newArr = [];
arr.forEach(function(currentValue, index, arr) {
currentValue.id = index + 1;
newArr.push(currentValue);
}, arr);
//console.log("arrObj:", newArr);
var sorted = newArr.sort(function(a, b) {
return b[Object.keys(b)[0]] - a[Object.keys(a)[0]];
});
console.log("sorted:", sorted);
EDIT: new based on comment
var arr = [{
one: 2
}, {
two: 3
}, {
three: 4
}, {
four: 1
}];
const newArr = [];
arr.forEach(function(currentValue, index, arr) {
let newValue = {};
newValue.text = Object.keys(currentValue)[0];
newValue.Value = currentValue[Object.keys(currentValue)[0]];
newValue.id = index + 1;
newArr.push(newValue);
}, arr);
//console.log("arrObj:", newArr);
var sorted = newArr.sort(function(a, b) {
return b.Value - a.Value;
});
console.log("sorted:", sorted);
output of this last is
sorted: [
{
"text": "three",
"Value": 4,
"id": 3
},
{
"text": "two",
"Value": 3,
"id": 2
},
{
"text": "one",
"Value": 2,
"id": 1
},
{
"text": "four",
"Value": 1,
"id": 4
}
]

Related

Value change in 1 object changes in all objects in array

I have an array of objects. Each object has a key quantity and value. I want to duplicate each object in the array based on its quantity. Next, I want to manipulate only one of the duplicated object in the array. But on manipulating value of 1 object, value of all duplicated objects change. Here is my code:
let arr = [
{ id: 1, quantity: 3, value: 10 },
{ id: 2, quantity: 1, value: 5 },
{ id: 2, quantity: 5, value: 5 },
];
const newArr = [];
for (const a of arr) {
if (a.quantity > 1) {
let quantity = a.quantity;
a.quantity = 1;
while (quantity--) {
newArr.push(a);
}
}
}
arr = newArr;
arr[0].value = 1;
When I changed the value of arr[0] to 1, value field of arr[1] and arr[2] also changed to 1.
I have tried copying the object using spread operator and JSON.parse(JSON.parse()), but none has worked.
Because newArr.push(a) .a push to newArr ref to element of arr
You can edit same as :
let arr = [
{ id: 1, quantity: 3, value: 10 },
{ id: 2, quantity: 1, value: 5 },
{ id: 2, quantity: 5, value: 5 },
]
const newArr = []
for (const a of arr) {
if (a.quantity > 1) {
let quantity = a.quantity;
a.quantity = 1;
while (quantity--) {
newArr.push({...a})
}
}
}
arr = [...newArr]
arr[0].value = 1
console.log(arr)
// example for Memory Management
let a = { id: 1, quantity: 3, value: 10 }
let b = { id: 1, quantity: 3, value: 10 }
let c = arr[0]
let d = {...arr[0]}
console.log(a === arr[0]) // false : different allocates memory for contain value
console.log(a === b) // false : different allocates memory for contain value
console.log(c === arr[0]) // true : refer to a memory
console.log(d === arr[0]) // false : different allocates memory for contain value

for loop inside array filter method [duplicate]

This question already has an answer here:
trying to use a for loop with if else statement in objects
(1 answer)
Closed 1 year ago.
Let say I have two arrays
From here I want to filter arr1 with arr2 condition (assuming arr2 = arr1 id).
I have tried this code but only return first condition.
const arr1 = [{
id: 1,
name: "Jhon"
},
{
id: 2,
name: "Barbara"
},
{
id: 3,
name: "Rio"
}
];
const arr2 = [1, 2, 5];
const filter = (arr1, arr2) => {
const output = arr1.filter(value => {
for (let i = 0; i < arr2.length; i++) {
if (value.id !== arr2[i]) {
return false;
}
return true;
}
})
console.log(output);
};
filter(arr1, arr2);
// output = [{id: 1, name: "Jhon"}]
// intended output [{id: 1, name: "Jhon"}, {id: 2, name: "Barbara}]
Anyone can tell me what I'm missing? Thank you
See the dupe why it did not work and then vastly simplify this
const arr1 = [{ id: 1, name: "Jhon" }, { id: 2, name: "Barbara" }, { id: 3, name: "Rio" } ];
const arr2 = [1, 2, 5];
const filter = (arr1, arr2) => arr1.filter(({id}) => arr2.includes(id))
console.log(filter(arr1,arr2))

How to filter an Array with another Array

I have an Array of Objects:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
I have a second array containing the ID's that I want to filter out of the first Array:
const ids = [1, 2]
How do I create a new Array of Objects without the ID's found in ids.
This is a fairly simple filter operation
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
var result = array.filter( x => !ids.includes(x.id));
console.log(result);
If you need to mutate the original array you can do like this:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
ids.forEach(idToDelete => {
const index = array.findIndex(({ id }) => id === idToDelete);
array.splice(index, 1);
});
console.log(array);
If you need a new array you can do like this:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
const result = array.filter(({ id }) => !ids.includes(id));
console.log(result);
You could also reassign a new array to the array variable:
let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
array = array.filter(({ id }) => !ids.includes(id));
console.log(array);
Use Array.filter :
let array = [
{id: 1, bar: "test" },
{id: 2, bar: "test2" },
{id: 3, bar: "test3" }
];
let ids = [1,2];
let filteredArray = array.filter(row=>!ids.includes(row.id));
console.log(filteredArray);
Use this oneliner from lodash.
const _ = require("lodash");
let filteredArray = _.remove(array, el=>[1,2].includes(el.id))
Use filter and indexOf.
const arr = [{ id: 1, bar: 'test' }, { id: 2, bar: 'test2' }, { id: 3, bar: 'test3' }];
const ids = [1, 2];
const result = arr.filter(element => ids.indexOf(element.id) === -1);
console.log(result);
We can filter an array in JavaScript using Array filter()
const myArray = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
const ids = [1,2]
const resultArray = myArray.filter(item => !ids.includes(item.id));
console.log(resultArray);
In term of performance the best solution will be the next one:
let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1,2];
const idSet = new Set();
for (const id of ids) {
idSet.add(id);
}
array = array.filter(x => !set.has(x.id));
//const newArray if you need the initial array unmodified
In this case we perform two consequencial iteration instead of a nested one, so the time complexity will be O(n) instead of O(n^2);
##Edit
If you instead need the initial array to be mutated and not overwritten you can use this approach:
const ids = [1,2];
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
for (const id of ids) {
const index = array.findIndex(x => x.id == id);
array.splice(index, 1);
}
In the second case the time complexity will be O(n*m), where n is array length and m is ids length.
I want to propose something wildly different.
In my case, I wanted to filter one list of unique IDs against another.
I was curious if regex could do it faster.
Such a method really only works with one-dimensional arrays of simple objects.
It's probably best if items a single regex 'word' (string of 0-9a-z_).
A list of ids works perfect.
array.filter works best on small datasets (1,000), usually slightly faster
regex worked 66% faster on large datasets (10,000)
regex speed advantage widens. 90% faster on 100,000.
On comparing two arrays of 1m items, filter didn't do anything for me after more than 90 seconds. Regex returned a result in six seconds.
In this case, the input is number[], and the output is string[], which works for my purposes, but you can use map to convert back to numbers if you need, .
var listlength = 10000;
function createArray() {
let arr = new Set();
for (let i = 0; i < listlength; i++) {
arr.add(Math.floor(Math.random() * listlength));
}
return arr;
}
function filter() {
let arr1 = Array.from(createArray());
let arr2 = Array.from(createArray());
let start = +new Date();
let arr3 = arr1.filter((n) => !arr2.includes(n));
console.log('filter', (+new Date() - start) + 'ms', arr1.length, arr2.length, arr3.length);
}
function regex() {
let arr1 = Array.from(createArray());
let arr2 = Array.from(createArray());
let start = +new Date();
let str1 = arr1.join(',') + ',';
str1 = str1.replace(new RegExp('\\b(' + arr2.join('|') + '),', 'g'), '');
let result = str1.split(',') // .map(e=>Number(e)); (to convert back to number[])
result.pop();
console.log('regex', (+new Date() - start) + 'ms', arr1.length, arr2.length, result.length);
}
for (let x = 0; x < 10; x++) {
console.log(`try ${x}`);
filter();
regex();
}
On my NodeJS app, sets of 100,000, regex more than 90% faster.

relative complement of A in B with functional programming

I have to retrieve the values that exist only on Array B, but do not exist on Array A.
From my research, It is called:
relative complement of A in B
Values in the arrays may not be primitives.I need an efficient and functional apporach to this problem.
I have found lodash _.without function, but it supports only array of primitive numbers.
Array A:
[{
id: 1
},
{
id:2
}]
Array B:
[{
id:2
},
{
id:3
}]
result should be:
[{
id:3
}]
this object is the only one who exist on Array B, but not on Array A.
You could use a comparison function which takes two objects and check the id for unequalness.
var aa = [{ id: 1 }, { id: 2 }],
bb = [{ id: 2 }, { id: 3 }],
comparison = (a, b) => a.id !== b.id,
result = bb.filter(b => aa.every(a => comparison(a, b)));
console.log(result);
With a check for equalness
var aa = [{ id: 1 }, { id: 2 }],
bb = [{ id: 2 }, { id: 3 }],
comparison = (a, b) => a.id === b.id,
result = bb.filter(b => aa.every(a => !comparison(a, b)));
console.log(result);
You can use array#filter with array#some. Iterate through arrB and check if the arrA contains that id using array#some and negate the result of array#some.
var arrA = [{id: 1},{id:2}],
arrB = [{id:2},{id:3}],
result = arrB.filter(({id}) => !arrA.some(o => o.id === id));
console.log(result);
You can use array.prototype.filter and array.prototype.findIndex:
var arrayA = [{ id: 1 }, { id: 2 }];
var arrayB = [{ id: 2 }, { id: 3 }];
var result = arrayB.filter(b => arrayA.findIndex(a => a.id === b.id) === -1);
console.log(result);
If you want to use lodash, _.differenceBy could be of use:
relativeComplementOfAinB = _.differenceBy(arrayB, arrayA, v => v.id);

Merge 2 object with same key, value from 2 array

I want to merge 2 object with same key, value from 2 array, something like this:
var arr1 = [
{ a: "a", 1: 1, 2: 2 },
{ a: "b", 1: 1, 2: 3 }
];
var arr2 = [
{ a: "a", 3: 123 },
{ a: "b", 3: 4411 }
];
var arr3 = _.map(arr1, function(a1) {
var a3 = {};
_.map(arr2, function(a2) {
if (a1.a == a2.a) {
a3 = _.extend(a1, a2);
}
})
return a3
});
result:
arr3 = [
{ '1': 1, '2': 2, '3': 123, a: 'a' },
{ '1': 1, '2': 3, '3': 4411, a: 'b' }
]
Does it look stupid? Are there any others ways to do this?
Thanks for reading.
Use a lodash chain to concat the arrays, group similar objects, and then merge each group to a single object:
var arr1 = [{ a: "a", 1: 1, 2: 2 }, { a: "b", 1: 1, 2: 3 }];
var arr2 = [{ a: "a", 3: 123 }, { a: "b", 3: 4411 }];
var result = _(arr1)
.concat(arr2) // concat the 2nd array
.groupBy('a') // group by the identical key
.map(_.spread(_.curry(_.merge, {}))) // left currey merge to to create a new empty object, and spread the group as parameters
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
With ES6 you can use Array#reduce to collect the similar objects in a Map, then get the Map#values iterator, and use the spread syntax to convert to an array:
const arr1 = [{ a: "a", 1: 1, 2: 2 }, { a: "b", 1: 1, 2: 3 }];
const arr2 = [{ a: "a", 3: 123 }, { a: "b", 3: 4411 }];
const result = [...arr1.concat(arr2) // concat the arrays
.reduce((m, o) => m.set(o.a, Object.assign(m.get(o.a) || {}, o)), // use a map to collect similar objects
new Map()
).values()]; // get the values iterator of the map, and spread into a new array
console.log(result);
you can do
var arr1 = [
{ a: "a", 1: 1, 2: 2 },
{ a: "b", 1: 1, 2: 3 }
];
var arr2 = [
{ a: "a", 3: 123 },
{ a: "b", 3: 4411 }
];
let result = arr1.map((e) => {
for(let element of arr2){
if(e.a == element.a) Object.assign(e, element);
}
return e;
});
console.log(result);

Categories

Resources