Rearrange index of array to match other array - javascript

I have two arrays containing the same elements but in different order, like this:
var arr1 = [{name: 'Bob', age: 24}, {name: 'Mary',age: 45}, {random: props}];
var arr2 = [{name: 'Mary', age:45 }, {name: 'Bob',24}, {other: randomProps}];
In this case of course a simple reverse() would do the trick but it might be an array with 10 objects in a random order.
Since both arrays always contains some common properties (name) I should be able to rearrange one array to match the other based on name.
Any tips on how to go about this?

Maybe something like this then? But this assumes that each object in the array has the name property.
var arr1 = [{name: 'Bob', age: 24}, {name: 'Mary',age: 45}, {random: props}];
var arr2 = [{name: 'Mary', age:45 }, {name: 'Bob',24}, {other: randomProps}];
function sortArray(arr) {
arr.sort(function(a, b) {
return a.name > b.name;
});
}
sortArray(arr1);
sortArray(arr2);

I think you can scan the arranged array and search elements in the second array and put them in a new array.
new_array;
foreach(element in array_ordered)
{
temp = search(element[name], array_unordered);
if(temp != null)
new_array.add(temp);
}

Related

How could I go about appending array elements to an array of objects in Javascript?

For example, let's say I have the following:
let data = [{name: "Bob"}, {name: "Alice"}]
let numArr = [12, 34]
I'd like this as the result:
let newData = [{name: "Bob", number: 12}, {name: "Alice", number: 34}]
Using Array#map:
const
data = [{name: "Bob"}, {name: "Alice"}],
numArr = [12, 34];
const newData = data.map((e, i) => ({ ...e, number: numArr[i] }));
console.log(newData);
You can use Symbol.iterator and forEach.
let data = [{name: "Bob"}, {name: "Alice"}];
let numArr = [12, 34];
ns=numArr[Symbol.iterator]();
data.forEach((d)=>d.number=ns.next().value);
document.write(JSON.stringify(data));
You need to define the iterated array outside of the forEach loop, otherwise the definition is re-initiated with every pass, and returns the same value each time.

How to merge objects from two different arrays of same length?

I am working in vanilla JavaScript.
I have two arrays of the same length.
Each of them is containing objects.
I need to create one array with objects combined.
How?
So, in code, my input is:
const arr1 = [{name: "John"}, {name: "Peter"}];
const arr2 = [{age: 56}, {age: 22}]
Desirable output:
const arr3 = [{name: "John", age: 56}, {name: "Peter", age: 22}]
I saw solution that ES6 offers, and it goes like this:
const object1 = {
name: 'John'
}
const object2 = {
age: 56
}
const object3 = {...object1, ...object2 }
That works just great! I would like to implement this same solution in this example whit objects in arrays using this spread operator. How? :)
Thank you.
Using Array.prototype.map() and spread syntax:
const arr1 = [{ name: 'John' }, { name: 'Peter' }];
const arr2 = [{ age: 56 }, { age: 22 }];
const arr3 = arr1.map((v, i) => ({ ...v, ...arr2[i] }));
console.log(arr3);
Another option
const arr1 = [{name: "John"}, {name: "Peter"}];
const arr2 = [{age: 56}, {age: 22}];
const result = [];
for(let i = 0; i < arr1.length; i++) result.push(Object.assign(arr1[i], arr2[i]));
console.log(result)
P.S, also as #charlietfl mentioned: if you don't want to mutate objects in arr1 start with empty object ... Object.assign({},arr1[i], arr2[i])

javascript Filter array with duplicate elements at a specific occurrence

I have an array of names which all have duplicates.
let arr = ['John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'];
I want to create a new array with some of the duplicate elements, specifying an instance at which they occur.
For example, I may want the array to contain only the second occurrence of John, Jack and June. The array will look like this:
'John', 'Jack', 'June'
To accomplish this, I have declared an object ni and looped through arr to add properties to the object corresponding to each name; the property will hold the value of an array containing each index at which the name occurs.
let ni = {};
for(let i = 0; i < arr.length; i++) {
let name = arr[i];
if(nc.hasOwnProperty(name)) {
ni[name].push(i);
} else {
ni[name] = [i];
}
}
console.log(ni);
// > Object { John: Array [0, 2], Jack: Array [1, 3, 4], June: Array [5, 6] }
In my Array.filter function, I check if the element's index is equal to index 1 of the object property corresponding to the same name.
let newArr = arr.filter(function(name) {
if(ni.hasOwnProperty(name)) {
return arr.indexOf(name) === ni[name][1];
}
});
This should return John at index 2, Jack at index 3, and June at index 6 to the new array.
However, this has not worked. Logging newArr to the console will output an array completely unchanged from the original.
> Array ["John", "Jack", "John", "Jack", "Jack", "June", "June"]
You can use some simple array logic like so:
let newArr = arr.filter((e, i) => i == ni[e][1]);
You can use reduce to count the occurrence of each name. If the name's count is 2, then push to another array. This way you don't have to run nested array methods:
const array = ['Jane', 'John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'];
const filtered = [];
const count = array.reduce((a, name) => {
a[name] = a[name] + 1 || 1;
if(a[name] === 2)
filtered.push(name)
return a;
}, {});
console.log(filtered)
Or get the keys of the counter with count > 1
const array = ['Jane', 'John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'],
count = array.reduce((a, n) => (a[n] = a[n] + 1 || 1, a), {}),
filtered = Object.keys(count).filter(n => count[n] > 1);
console.log(filtered)
I'm creating an object instead of an array because it seems more suitable to map from name to the index of the 2nd appearance. It works like this: indexOf returns the index of the 1st occurrence of an element in the array so if indexOf is not equal to the current index then it's 2nd or later occurrence, then I check whether the name is not already in the return object so I know it's not 3rd or later occurrence.
let arr = ['John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'];
let newObj = arr.reduce(function(acc, cur, idx) {
if (arr.indexOf(cur)!==idx && !acc[cur]) { acc[cur] = idx; }
return acc;
}, {});
console.log(newObj);

javascript keep certain properties across objects in array

I want to remove every attribute from objects in array except for some of them:
var listToKeep = ['name', 'school'];
var arrayOfObjects = [{id:'abc',name:'oh', school: 'a', sport: 'a'},
{id:'efg',name:'em', school: 'b', sport: 's'},
{id:'hij',name:'ge', school: 'c', sport: 'n'}]
I am trying with this, but this is only trying to remove one:
arrayOfObjects .forEach(function(v){ delete v.id});
the expected result will be:
var arrayOfObjects = [{name:'oh', school: 'a'},
{name:'em', school: 'b'},
{name:'ge', school: 'c'}]
i don't want to use for loop.
You can map each item in your array to new one, created by reducing list of keys to keep:
const newArray = arrayOfObjects.map(obj => listToKeep.reduce((newObj, key) => {
newObj[key] = obj[key]
return newObj
}, {}))
If you want to mutate original objects and delete properties, you can use two forEach loops and delete operator:
arrayOfObjects.forEach(obj => listToKeep.forEach((key) => {
delete obj[key]
}, {}))
If you can use lodash or similar library, you can pick properties of object, e.g.:
const newArray = arrayOfObjects.map(obj => _.pick(obj, listToKeep))
You can loop over the keys of each JSON object in the arrayOfObjects array and then if the key is not found in the array listToKeep then remove that key:value from the object. And since you want to change the existing arrayOfObjects so you can follow this approach to use delete on the object property.
var listToKeep = ['name', 'school'];
var arrayOfObjects = [{id:'abc',name:'oh', school: 'a', sport: 'a'},
{id:'efg',name:'em', school: 'b', sport: 's'},
{id:'hij',name:'ge', school: 'c', sport:'n'}];
arrayOfObjects.forEach((obj)=>{
Object.keys(obj).forEach((key)=>{
if(listToKeep.indexOf(key) === -1){
delete obj[key];
}
});
});
console.log(arrayOfObjects);

Lodash: How to add new field to all values in collection

Example:
var arr = [{name: 'a', age: 23}, {name: 'b', age: 24}]
var newArr = _.enhance(arr, { married : false });
console.log(newArr); // [{name: 'a', age: 23, married : false}, {name: 'b', age: 24, married : false}]
I'm looking for something to do this. Note, enhance is not present in lodash.
Is it possible to do this with lodash?
If not -- possible addition?
Thanks,
You probably want to extend each of your objects.
mu is too short sort of killed my wordplay while making an excellent point. Updated to create an entirely new array.
var arr = [{name: 'a', age: 23}, {name: 'b', age: 24}];
var newArr = _.map(arr, function(element) {
return _.extend({}, element, {married: false});
});
If you want to add it to the library,
_.enhance = function(list, source) {
return _.map(list, function(element) { return _.extend({}, element, source); });
}
I use ES6 syntax. I think this will help to u.
var arr = [{name: 'a', age: 23}, {name: 'b', age: 24}];
arr.map((element) => {
return element.married = false;
});
console.log(arr); // [{name: 'a', age: 23, married : false}, {name: 'b', age: 24, married : false}]
Using lodash and ES6 arrow notation the solution can become quite short:
const newArr = _.map(arr, o => _.extend({married: false}, o));
Note: I use the object {married: false} as the first argument since mutating this object leaves the original array intact. This means however that married becomes the first field in the resulting object, but this is probably not relevant.
ES6 with Map and Spread
const arr = [{name: 'a', age: 23}, {name: 'b', age: 24}, {name: 'c', age: 25}];
const newArr = arr.map(el => ({ ...el, married: false }));
console.log(newArr);
// [{age: 23, married: false, name: 'a'}, {age: 24, married: false, name: 'b'}, {name: 'c', age: 25, married: false}]
Note: Arrow functions returing an object literal need to wrap the object with parenthesis, e.g., () => ({})
The function lodash has that is closest to what you want is merge: http://lodash.com/docs#merge
The only slight difference between how merge works and what you want to do is you would need to have an array of equal length to arr all that looks like:
var arr = [{name: 'a', age: 23}, {name: 'b', age: 24}];
var marriedArr = [{married : false}, {married : false}];
var newArr = _.merge(arr, marriedArr);
console.log(newArr);
If you attempt to do:
var newArr = _.merge(arr, {married : false});
Then merge will work just like concat.
This comes late and it doesn't involve lodash, but I think the cleanest solution if you want the old data mutable is to use a classic for loop iteration. This way you won't load up the memory with a new array.

Categories

Resources