I have an array under bahrein that I would like ordered by the index of each item. My bare code is as shown below.
var bahrein = [
{id: 1, name: "Josef"},
{id: 3, name: "Billy"},
{id: 0, name: "Jane"},
{id: 2, name: "Mack"}
];
for (i = 0; i < bahrein.length; i++){
document.getElementById("show").innerHTML += "<p>"+bahrein[i].name+"</p>";
}
<div id="show"></div>
I have ids assigned for each item, but I placed them out of order. What I would like to know is how to programatically use the sort() function to list the names on my list in order.
Right now my innerHTML shows the list in the order they are written (ie: Josef, Billy, Jane, and Mack). I want to show them in the order of their ID (ie: Jane, Josef, Mack, Billy).
You can use sort() method on your data and then append it to html.
var bahrein = [{id: 1, name: "Josef"},{id: 3, name: "Billy"},{id: 0, name: "Jane"},{id: 2, name: "Mack"}];
let show = document.getElementById("show")
bahrein
.sort((a, b) => a.id - b.id)
.forEach(e => show.innerHTML += `<p>${e.name}</p>`)
<div id="show"></div>
You could also create string of sorted html and then append it html.
var bahrein = [{id: 1, name: "Josef"},{id: 3, name: "Billy"},{id: 0, name: "Jane"},{id: 2, name: "Mack"}];
let sorted = bahrein
.sort((a, b) => a.id - b.id)
.map(e => `<p>${e.name}</p>`)
.join('')
document.getElementById("show").innerHTML = sorted
<div id="show"></div>
It doesn't answer your question, but you can use "lodash" to do the same.
var bahrein = [
{id: 1, name: "Josef"},
{id: 3, name: "Billy"},
{id: 0, name: "Jane"},
{id: 2, name: "Mack"}
];
bahrein = _.orderBy(bahrein , ['id'],['asc']);
You can learn more about it here.
Related
I have three arrays of objects like so
const arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}];
const arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}];
const arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}];
and I want to merge them into a single array like this
const bigArray = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'},{id: 3, name: 'Pete'}, {id: 4, name: 'Liam'}, {id: 5, name: 'Baby'}, {id: 6, name: 'Neeson'}, {id: 7, name: 'Kobe'}];
I know I can spread them into a single array using the spread operator but I also need the IDs incremented when they are joined. How can I achieve that?
Reassign the id based on the index:
const merged = [...arr1, ...arr2, ...arr3];
merged.forEach((el, index) => el.id = index + 1);
Add all the array in a single array and than map over it and change index according to need.
const arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}];
const arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}];
const arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}];
let arr = [...arr1,...arr2,...arr3]
let op = arr.map((ele, index) => ({...ele, id: index+1}) )
console.log(op)
You can combine the arrays to a single array using rest parameters and Array.flat(), and then you can use Array.map() to update the objects with the id generated from the index:
const flatAndInc = (...args) =>
args.flat()
.map((o, idx) => ({
...o,
id: idx + 1
}));
const arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}];
const arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}];
const arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}];
const result = flatAndInc(arr1, arr2, arr3);
console.log(result);
You could map new objects without mutating the given data.
const
arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}],
arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}],
arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}],
result = [arr1, arr2, arr3].reduce(
(id => (r, a) => (a.forEach(({ name }) => r.push({ id: id++, name })), r))(1),
[]
);
console.log(result);
All of the other answers are valid, and are mostly more efficient and easier than mine. However, my answer is one of the easiest to understand.
My code uses Spread Syntax (...) to create the big array, but all that does is combines the arrays. Then, I use a .forEach() loop to loop through the array, and redefine the id. Then I incremented the id variable, so that the id's were in order.
const arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}];
const arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}];
const arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}];
let id = 1;
const bigArray = [...arr1, ...arr2, ...arr3];
bigArray.forEach(e => {
e.id = id;
id++;
});
console.log(bigArray);
You can use Array.from and spread
const arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}];
const arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}];
const arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}];
var result = Array.from([...arr1, ...arr2, ...arr3], ({name}, i)=>{ return {id: i + 1, name} });
console.log(result);
You can use reduce() map() and Spread Syntax.
Pass an array of all the arrays you want to merge to function
Flat that array using spread operator.
Then use reduce() to convert all the arrays to single dimensional array.
At last use map() and set it id property to index + 1
const arr1 = [{id: 1, name: 'Jay'}, {id: 2, name: 'Kay'}];
const arr2 = [{id: 1, name: 'Pete'}, {id: 2, name: 'Liam'}];
const arr3 = [{id: 1, name: 'Baby'}, {id: 2, name: 'Neeson'}, {id: 3, name: 'Kobe'}];
function merge(arrays){
return [...arrays].reduce((ac,a) => [...ac,...a],[]).map((x,i) => ({...x,id:i+1}));
}
console.log(merge([arr1,arr2,arr3]));
I have arrays of objects that look like this:
const array1 = [{id: 1, name: "John"}, {id: 2, name: "Mary"}]
const array2 = [{id: 1, name: "John"}, {id: 3, name: "Phil"}, {id: 4, name: "Sarah"}]
How can I add unique objects from array2 to array1 so it looks like this:
const array1 = [{id: 1, name: "John"}, {id: 2, name: "Mary"}, {id: 3, name: "Phil"}, {id: 4, name: "Sarah"}]
Lodash implementations are permitted. Thanks a lot.
You can use _.unionBy() function to merge unique objects from arrays.
const array1 = [{id: 1, name: "John"}, {id: 2, name: "Mary"}];
const array2 = [{id: 1, name: "John"}, {id: 3, name: "Phil"}, {id: 4, name: "Sarah"}];
console.log(_.unionBy(array1, array2, 'id'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Using native array functions you can get the desired result as follows:
Concat both arrays first using .concat()
Use .reduce() to create the resultant object having ids as keys and values as relevant object. If already added an object then skip the others with same ids.
Use Object.values() to get an array of the objects from the resultant object.
Demo:
const array1 = [{id: 1, name: "John"}, {id: 2, name: "Mary"}],
array2 = [{id: 1, name: "John"}, {id: 3, name: "Phil"}, {id: 4, name: "Sarah"}];
const result = Object.values(
array1.concat(array2).reduce((r, c) => (r[c.id] = r[c.id] || c, r), {})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can also do it in one line via native Map object and reduce:
const arr1 = [{id: 1, name: "John"}, {id: 2, name: "Mary"}]
const arr2 = [{id: 1, name: "John"}, {id: 3, name: "Phil"}, {id: 4, name: "Sarah"}]
const result = [...[...arr1, ...arr2]
.reduce((r, c) => (r.set(c.id, c), r), new Map()).values()]
console.log(result)
I'm trying to iterate over an existing array with of objects with a 'quantity' property and rebuild it by a control value.
let cart = [{id: 1, name: 'Pizza', quantity: 5, specialId: 0},
{id: 2, name: 'Burger', quantity: 2, specialId: 0}];
I have a control of 3 items i.e. for every 3 items you get a discount so I'd like to reconstitute the cart array as follows:
cart = [{id: 1, name: 'Pizza', quantity: 3, specialId: 1},
{id: 2, name: 'Pizza', quantity: 2, specialId: 2},
{id: 3, name: 'Burger', quantity: 1, specialId: 2},
{id: 4, name: 'Burger', qty: 1, specialId: 0}]
I've looked at several ways of doing this mostly around creating a new array of single quantity items and then creating another final array but surely that isn't very efficient?
I'd appreciate any pointers. I have a horrible feeling I'm missing something simple and have stared at this too long.
If I understand correctly the amount of three is ignorant of the type of product, so the second batch of three (in your example) consists of 2 pizzas and 1 burger.
The specialId seems to be unique and non-zero for every complete set of three (where every item in that set shares that specialId value), and zero for any remaining item(s).
Finally, it seems that the id in the result is unrelated to the input, but just an incremental number.
Here is how you could do that:
function splitBy(cart, size) {
const result = [];
let quantity = 0;
let grab = size;
let specialId = 1;
let id = 1;
for (let item of cart) {
for (quantity = item.quantity; quantity >= grab; quantity -= grab, grab = size, specialId++) {
if (result.length && !result[result.length-1].specialId) result[result.length-1].specialId = specialId;
result.push(Object.assign({}, item, {quantity: grab, specialId, id: id++}));
}
if (quantity) result.push(Object.assign({}, item, {quantity, specialId: 0, id: id++}));
grab = size - quantity;
}
return result;
}
const cart = [{id: 1, name: 'Pizza', quantity: 5, specialId: 0},
{id: 2, name: 'Burger', quantity: 2, specialId: 0}];
const result = splitBy(cart, 3)
console.log(result);
Basically you have two options.
loop over the current cart, and if the quantity is over 3, split it to two, and push them both.
split the array, and then merge it together.
My guess is to go with the first option, doing something like this:
var cart = [{id: 1, name: 'Pizza', quantity: 5, specialId: 0},
{id: 2, name: 'Burger', quantity: 2, specialId: 0}];
var a = [];
cart.forEach(x => {
if (x.quantity > 3) {
let temp = {...x};
temp.quantity = 3;
a.push(temp);
x.quantity -= 3;
}
a.push(x)
});
I have an array which is dynamically created by selecting items from a list:
[2, 4]
I also have an array of objects:
[{id: 1, name: "Param1"}, {id: 2, name: "Param2"}, {id: 3, name: "Param3"}, {id: 4, name: "Param4"}]
What I need to do is use the values in the first array to match against the ids in the objects in the second array and return those objects.
Help with this would be much appreciated
Thanks for your time
You can use this ES6 code, which turns the first array to a Set to allow fast lookup, and then applies the Array filter method, specifically intended for this purpose:
var select = [2, 4];
var data = [{id: 1, name: "Param1"}, {id: 2, name: "Param2"},
{id: 3, name: "Param3"}, {id: 4, name: "Param4"}]
var selectSet = new Set(select);
var result = data.filter( obj => selectSet.has(obj.id) );
console.log(result);
You can just use for loop as Liam's comment, or you can use the filter method of array like this:
var keys = [2, 4];
var objs = [{id: 1, name: "Param1"}, {id: 2, name: "Param2"}, {id: 3, name: "Param3"}, {id: 4, name: "Param4"}];
function filterById(obj) {
return keys.indexOf(obj.id) != -1;
}
var newArr = objs.filter(filterById);
The newArr is the result you want.
I have two arrays of objects like this:
var arr1 = [{Id: 1, Name: "Test1"}, {Id: 2, Name: "Test2"}, {Id: 3, Name: "Test3"}, {Id: 4, Name: "Test4"}]
var arr2 = [{Id: 1, Name: "Test1"}, {Id: 3, Name: "Test3"}]
I need to compare the elements of the two arrays by Id and remove the elements from arr1 that are not presented in arr2 ( does not have element with that Id). How can I do this ?
var res = arr1.filter(function(o) {
return arr2.some(function(o2) {
return o.Id === o2.Id;
})
});
shim, shim, shim.
You can use a function that accepts any number of arrays, and returns only the items that are present in all of them.
function compare() {
let arr = [...arguments];
return arr.shift().filter( y =>
arr.every( x => x.some( j => j.Id === y.Id) )
)
}
var arr1 = [{Id: 1, Name: "Test1"}, {Id: 2, Name: "Test2"}, {Id: 3, Name: "Test3"}, {Id: 4, Name: "Test4"}];
var arr2 = [{Id: 1, Name: "Test1"}, {Id: 3, Name: "Test3"}, {Id: 30, Name: "Test3"}];
var arr3 = [{Id: 1, Name: "Test1"}, {Id: 6, Name: "Test3"}, {Id: 30, Name: "Test3"}];
var new_arr = compare(arr1, arr2, arr3);
console.log(new_arr);
function compare() {
let arr = [...arguments]
return arr.shift().filter( y =>
arr.every( x => x.some( j => j.Id === y.Id) )
)
}
Making use of a hash (a Set) will give a performance gain:
var arr1 = [{Id: 1, Name: "Test1"}, {Id: 2, Name: "Test2"},
{Id: 3, Name: "Test3"}, {Id: 4, Name: "Test4"}];
var arr2 = [{Id: 1, Name: "Test1"}, {Id: 3, Name: "Test3"}];
arr1 = arr1.filter(function (el) {
return this.has(el.Id);
}, new Set(arr2.map(el => el.Id)));
console.log(arr1);
A new Set is created that gets the Id values from arr2:
"1","3"
That Set is passed as the thisArg to filter, so that within the filter callback it is available as this.