How to make an array of objects from an array of elements - javascript

This is driving me crazy.
I have an array like so:
myArray = ['A', 'B', 'C', 'D', 'E', 'F', ];
and my code is making a NEW object that will look like this:
myNewObj = [
{
name: "A",
displayName: "A"
},
{
name: "B",
displayName: "B"
},
{
name: "C",
displayName: "C"
},
{
name: "C",
displayName: "C"
},
{
name: "D",
displayName: "D"
},
{
name: "E",
displayName: "E"
},
{
name: "F",
displayName: "F"
}
]
My code gets values in the myArray and I want to create myNewObj
This is how I'm doing it so far
I create the new object
let newObj = [{
"name": "",
"displayName": ""
}];
Then I use a simple FOR NEXT loop and it work up until a point and claims newObj[i].name IS UNDEFINED... how is that possible when I'm defining it and see it in the Google dev console?
for (let i = 0; i < myArray.length; i++) {
newObj[i].name = myArray[i];
newObj[i].displayName = myArray[i];
myNewObj.push(newObj);
}
However, I consistently get this error:
newObj[i].name is NOT DEFINED and it dies.
UPDATE: Everything's working and here's the ACTUAL real data
But as you can see, the prototype is there and when I save to sessionStorage, I get [Object,Object], x 12....
do I need to strip out name: and displayName: and put into yet another object?

Using Array#map:
const myArray = ['A', 'B', 'C', 'D', 'E', 'F'];
const myNewArray = myArray.map(e => ({ name: e, displayName: e }));
console.log(myNewArray);
Your solution (you need to initialize the array as [] and create a new object in every iteration to push it):
const myArray = ['A', 'B', 'C', 'D', 'E', 'F'];
const myNewArray = [];
for (let i = 0; i < myArray.length; i++) {
const obj = {};
obj.name = myArray[i];
obj.displayName = myArray[i];
myNewArray.push(obj);
}
console.log(myNewArray);

Issue with the code
You are doing the Array.Push incorrectly. Your let newObj should be an object, not an array. It should be initialized inside the loop. so that each execution takes a different memory location. You should define myNewObj as an empty array and should push your newObj into myNewObj array inside the loop.
Working Fiddle
const myArray = ['A', 'B', 'C', 'D', 'E', 'F'];
const myNewObj = [];
for (let i = 0; i < myArray.length; i++) {
let newObj = {
"name": "",
"displayName": ""
};
newObj.name = myArray[i];
newObj.displayName = myArray[i];
myNewObj.push(newObj);
};
console.log(myNewObj);
Better Approach
A better approach for this issue is to use Array.map. Array.map returns a new array from an existing array. You could run Array.map on myArray and construct myNewObj array as below.
Working Fiddle
const myArray = ['A', 'B', 'C', 'D', 'E', 'F'];
const myNewObj = myArray.map((item) => ({ name: item, dispayName: item}));
console.log(myNewObj)

var myArray = ['A', 'B', 'C', 'D', 'E', 'F', ];
var myNewObj = [];
for (let i = 0; i < myArray.length; i++) {
var newObj = {
name:'',
displayName:''
};
newObj['name'] = myArray[i];
newObj['displayName'] = myArray[i];
myNewObj.push(newObj);
}
console.log(myNewObj);

You're trying to define newObj as an array with one object for some reason. Just create a new object.
Create a new object within the scope of the loop for each iteration. You can then just push that object into the empty output array.
const letters = ['A', 'B', 'C', 'D', 'E', 'F'];
const arr = [];
for (let i = 0; i < letters.length; i++) {
const obj = {};
obj.name = letters[i];
obj.displayName = letters[i];
arr.push(obj);
}
console.log(arr);

Related

How to group together same elements into a new Array

Below is an array containing some elements:
const arr = ['a', 'b', 'c', 'a', 'b', 'c', 'd']
So how can I create a new array where same elements are grouped together into a new array like this:
const arr = [['a','a'], ['b','b'], ['c','c'], ['d']]
Thank you for your time.
This can be achieved with the most generic of group by operations.
const arr = ['a', 'b', 'c', 'a', 'b', 'c', 'd'];
const grouped = Object.values(arr.reduce((a, n) => ((a[n] ??= []).push(n), a), {}));
console.log(grouped);
This is one way to do it. More explicit, but easier to understand and translate to other languages as well. Time: O(n), Space: O(n), n is number of elements in array
function process(arr) {
const map = arr.reduce((acc, e) => {
if (!acc.has(e)) {
acc.set(e, 0);
}
acc.set(e, acc.get(e) + 1);
return acc;
}, new Map())
const res = [];
for (const[k, v] of map.entries()) {
const localRes = [];
for (let i = 1; i <= v; i++) {
localRes.push(k);
}
res.push(localRes);
}
return res;
}
const arr = ['a', 'b', 'c', 'a', 'b', 'c', 'd']
console.log(process(arr));
Result:
[ [ 'a', 'a' ], [ 'b', 'b' ], [ 'c', 'c' ], [ 'd' ] ]
The idea is to sort the array in ascending order, then iterate over it and take if the last char and the current char are the same and put them in an inner-array else create new inner-array of that char, do this process of accumulating till for loop iterate overall characters.
["a","a","b","b","c","c","d"]
//sort and do algorithm
["a","a","b","b","c","c","d"]
//^---^ ^---^
[["a","a"],["b","b"],["c","c"],["d"]]
Implementation:
const arr = ["a", "b", "c", "a", "b", "c", "d"];
const chars = arr.sort((a, b) => a.localeCompare(b));
console.log(chars);
let res = [[]],
lastChar = chars[0];
for (char of chars) {
if (char == lastChar) {
res[res.length - 1].push(char);
} else {
res.push([char]);
lastChar = char;
}
}
Result:
console.log(res); //[["a","a"],["b","b"],["c","c"],["d"]]

How do I convert an array to an object in JavaScript? [duplicate]

Is there a simple way in javascript to take a flat array and convert into an object with the even-indexed members of the array as properties and odd-indexed members as corresponding values (analgous to ruby's Hash[*array])?
For example, if I have this:
[ 'a', 'b', 'c', 'd', 'e', 'f' ]
Then I want this:
{ 'a': 'b', 'c': 'd', 'e': 'f' }
The best I've come up with so far seems more verbose than it has to be:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
for (var i = 0, len = arr.length; i < len; i += 2) {
obj[arr[i]] = arr[i + 1];
}
// obj => { 'a': 'b', 'c': 'd', 'e': 'f' }
Is there a better, less verbose, or more elegant way to do this? (Or I have just been programming in ruby too much lately?)
I'm looking for an answer in vanilla javascript, but would also be interested if there is a better way to do this if using undercore.js or jQuery. Performance is not really a concern.
Pretty sure this will work and is shorter:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
while (arr.length) {
obj[arr.shift()] = arr.shift();
}
See shift().
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = arr.reduce( function( ret, value, i, values ) {
if( i % 2 === 0 ) ret[ value ] = values[ i + 1 ];
return ret;
}, { } );
If you need it multiple times you can also add a method to the Array.prototype:
Array.prototype.to_object = function () {
var obj = {};
for(var i = 0; i < this.length; i += 2) {
obj[this[i]] = this[i + 1];
}
return obj
};
var a = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
a.to_object(); // => { 'a': 'b', 'c': 'd', 'e': 'f' }
You could first chunk your array into groups of two:
[['a', 'b'], ['c', 'd'], ['e', 'f']]
so that is is in a valid format to be used by Object.fromEntries(), which will build your object for you:
const chunk = (arr, size) => arr.length ? [arr.slice(0, size), ...chunk(arr.slice(size), size)] : [];
const arr = ['a', 'b', 'c', 'd', 'e', 'f'];
const res = Object.fromEntries(chunk(arr, 2));
console.log(res); // {a: "b", c: "d", e: "f"}
With underscore.js and lodash, you don't need to implement the chunk() method yourself, and can instead use _.chunk(), a method built into both libraries. The full lodash equivalent of the above would be:
// lodash
> _.fromPairs(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}
Using _.fromPairs provides better browser support, so if using lodash, it is preferred over Object.fromEntries()
Similarly, we can use _.object() if you're using underscore.js to build the object:
// underscore.js
> _.object(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}

Create object from two arrays

How can I create an object from two arrays without using loops in javascript.
example:
array1 = [1,2,3,4,5];
array2 = [A,B,C,D,E];
I want from below object
obj = {
'1': 'A',
'2': 'B',
'3': 'C',
'4': 'D',
'5': 'E',
}
Thanks in advance
var obj = {}
array1 = [1, 2, 3, 4, 5];
array2 = ['A', 'B', 'C', 'D', 'E'];
array1.forEach(function(value, index) {
obj[value] = array2[index];
});
console.log(obj);
Try to use $.each() to iterate over one of that array and construct the object as per your requirement,
var array1 = [1,2,3,4,5],array2 = ['A','B','C','D','E'];
var obj = {};
$.each(array2,function(i,val){
obj[array1[i]] = val;
});
DEMO
An ES6, array reduce solution.
const array1 = [1, 2, 3, 4, 5];
const array2 = ['A', 'B', 'C', 'D', 'E'];
const resultMap = array1.reduce(
(accumulator, value, index) => Object.assign(accumulator, {
[value]: array2[index],
}), {}
);
console.log(resultMap);
just for fun created something like this without using any iteration methods.
const array1 = [1,2,3,4,5];
const array2 = ['A','B','C','D','E'];
let combineKeyValueProxy = new Proxy({}, {
set: function(target, prop, value, receiver) {
target[array1[prop]] = value;
return true
}
});
const output = Object.assign(combineKeyValueProxy, array2);
console.log(output) // Proxy {1: "A", 2: "B", 3: "C", 4: "D", 5: "E"}

Remove all elements contained in another array [duplicate]

This question already has answers here:
How to get the difference between two arrays in JavaScript?
(84 answers)
Closed 5 months ago.
I am looking for an efficient way to remove all elements from a javascript array if they are present in another array.
// If I have this array:
var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
// and this one:
var toRemove = ['b', 'c', 'g'];
I want to operate on myArray to leave it in this state: ['a', 'd', 'e', 'f']
With jQuery, I'm using grep() and inArray(), which works well:
myArray = $.grep(myArray, function(value) {
return $.inArray(value, toRemove) < 0;
});
Is there a pure javascript way to do this without looping and splicing?
Use the Array.filter() method:
myArray = myArray.filter( function( el ) {
return toRemove.indexOf( el ) < 0;
} );
Small improvement, as browser support for Array.includes() has increased:
myArray = myArray.filter( function( el ) {
return !toRemove.includes( el );
} );
Next adaptation using arrow functions:
myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );
ECMAScript 6 sets can permit faster computing of the elements of one array that aren't in the other:
const myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
const toRemove = new Set(['b', 'c', 'g']);
const difference = myArray.filter( x => !toRemove.has(x) );
console.log(difference); // ["a", "d", "e", "f"]
Since the lookup complexity for the V8 engine browsers use these days is O(1), the time complexity of the whole algorithm is O(n).
var myArray = [
{name: 'deepak', place: 'bangalore'},
{name: 'chirag', place: 'bangalore'},
{name: 'alok', place: 'berhampur'},
{name: 'chandan', place: 'mumbai'}
];
var toRemove = [
{name: 'deepak', place: 'bangalore'},
{name: 'alok', place: 'berhampur'}
];
myArray = myArray.filter(ar => !toRemove.find(rm => (rm.name === ar.name && ar.place === rm.place) ))
The filter method should do the trick:
const myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
const toRemove = ['b', 'c', 'g'];
// ES5 syntax
const filteredArray = myArray.filter(function(x) {
return toRemove.indexOf(x) < 0;
});
If your toRemove array is large, this sort of lookup pattern can be inefficient. It would be more performant to create a map so that lookups are O(1) rather than O(n).
const toRemoveMap = toRemove.reduce(
function(memo, item) {
memo[item] = memo[item] || true;
return memo;
},
{} // initialize an empty object
);
const filteredArray = myArray.filter(function (x) {
return toRemoveMap[x];
});
// or, if you want to use ES6-style arrow syntax:
const toRemoveMap = toRemove.reduce((memo, item) => ({
...memo,
[item]: true
}), {});
const filteredArray = myArray.filter(x => toRemoveMap[x]);
If you are using an array of objects. Then the below code should do the magic, where an object property will be the criteria to remove duplicate items.
In the below example, duplicates have been removed comparing name of each item.
Try this example. http://jsfiddle.net/deepak7641/zLj133rh/
var myArray = [
{name: 'deepak', place: 'bangalore'},
{name: 'chirag', place: 'bangalore'},
{name: 'alok', place: 'berhampur'},
{name: 'chandan', place: 'mumbai'}
];
var toRemove = [
{name: 'deepak', place: 'bangalore'},
{name: 'alok', place: 'berhampur'}
];
for( var i=myArray.length - 1; i>=0; i--){
for( var j=0; j<toRemove.length; j++){
if(myArray[i] && (myArray[i].name === toRemove[j].name)){
myArray.splice(i, 1);
}
}
}
alert(JSON.stringify(myArray));
Lodash has an utility function for this as well:
https://lodash.com/docs#difference
How about the simplest possible:
var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var toRemove = ['b', 'c', 'g'];
var myArray = myArray.filter((item) => !toRemove.includes(item));
console.log(myArray)
I just implemented as:
Array.prototype.exclude = function(list){
return this.filter(function(el){return list.indexOf(el)<0;})
}
Use as:
myArray.exclude(toRemove);
You can use _.differenceBy from lodash
const myArray = [
{name: 'deepak', place: 'bangalore'},
{name: 'chirag', place: 'bangalore'},
{name: 'alok', place: 'berhampur'},
{name: 'chandan', place: 'mumbai'}
];
const toRemove = [
{name: 'deepak', place: 'bangalore'},
{name: 'alok', place: 'berhampur'}
];
const sorted = _.differenceBy(myArray, toRemove, 'name');
Example code here: CodePen
If you cannot use new ES5 stuff such filter I think you're stuck with two loops:
for( var i =myArray.length - 1; i>=0; i--){
for( var j=0; j<toRemove.length; j++){
if(myArray[i] === toRemove[j]){
myArray.splice(i, 1);
}
}
}
Now in one-liner flavor:
console.log(['a', 'b', 'c', 'd', 'e', 'f', 'g'].filter(x => !~['b', 'c', 'g'].indexOf(x)))
Might not work on old browsers.
This is pretty late but adding this to explain what #mojtaba roohi has answered. The first block of code will not work as each array is having a different object, i.e. df[0] != nfl[2]. Both objects look similar but are altogether different, which is not the case when we use primitive types like numbers.
let df = [ {'name': 'C' },{'name': 'D' }]
let nfl = [ {'name': 'A' },{'name': 'B' },{'name': 'C' },{'name': 'D' }]
let res = nfl.filter(x => df.indexOf(x)<0)
console.log(res)
Here is the working code:
let df = [{'name': 'C' },{'name': 'D' }]
let nfl = [ {'name': 'A' },{'name': 'B' },{'name': 'C' },{'name': 'D' }];
let res = nfl.filter((o1) => !df.some((o2) => o1.name === o2.name));
console.log(res)
If you're using Typescript and want to match on a single property value, this should work based on Craciun Ciprian's answer above.
You could also make this more generic by allowing non-object matching and / or multi-property value matching.
/**
*
* #param arr1 The initial array
* #param arr2 The array to remove
* #param propertyName the key of the object to match on
*/
function differenceByPropVal<T>(arr1: T[], arr2: T[], propertyName: string): T[] {
return arr1.filter(
(a: T): boolean =>
!arr2.find((b: T): boolean => b[propertyName] === a[propertyName])
);
}
Proper way to remove all elements contained in another array is to make source array same object by remove only elements:
Array.prototype.removeContained = function(array) {
var i, results;
i = this.length;
results = [];
while (i--) {
if (array.indexOf(this[i]) !== -1) {
results.push(this.splice(i, 1));
}
}
return results;
};
Or CoffeeScript equivalent:
Array.prototype.removeContained = (array) ->
i = #length
#splice i, 1 while i-- when array.indexOf(#[i]) isnt -1
Testing inside chrome dev tools:
19:33:04.447 a=1
19:33:06.354 b=2
19:33:07.615 c=3
19:33:09.981 arr = [a,b,c]
19:33:16.460 arr1 = arr
19:33:20.317 arr1 === arr
19:33:20.331 true
19:33:43.592 arr.removeContained([a,c])
19:33:52.433 arr === arr1
19:33:52.438 true
Using Angular framework is the best way to keep pointer to source object when you update collections without large amount of watchers and reloads.
I build the logic without using any built-in methods, please let me know any optimization or modifications.
I tested in JS editor it is working fine.
var myArray = [
{name: 'deepak', place: 'bangalore'},
{name: 'alok', place: 'berhampur'},
{name: 'chirag', place: 'bangalore'},
{name: 'chandan', place: 'mumbai'},
];
var toRemove = [
{name: 'chirag', place: 'bangalore'},
{name: 'deepak', place: 'bangalore'},
/*{name: 'chandan', place: 'mumbai'},*/
/*{name: 'alok', place: 'berhampur'},*/
];
var tempArr = [];
for( var i=0 ; i < myArray.length; i++){
for( var j=0; j<toRemove.length; j++){
var toRemoveObj = toRemove[j];
if(myArray[i] && (myArray[i].name === toRemove[j].name)) {
break;
}else if(myArray[i] && (myArray[i].name !== toRemove[j].name)){
var fnd = isExists(tempArr,myArray[i]);
if(!fnd){
var idx = getIdex(toRemove,myArray[i])
if (idx === -1){
tempArr.push(myArray[i]);
}
}
}
}
}
function isExists(source,item){
var isFound = false;
for( var i=0 ; i < source.length; i++){
var obj = source[i];
if(item && obj && obj.name === item.name){
isFound = true;
break;
}
}
return isFound;
}
function getIdex(toRemove,item){
var idex = -1;
for( var i=0 ; i < toRemove.length; i++){
var rObj =toRemove[i];
if(rObj && item && rObj.name === item.name){
idex=i;
break;
}
}
return idex;
}
//Using the new ES6 Syntax
console.log(["a", "b", "c", "d", "e", "f", "g"].filter(el => !["b", "c", "g"].includes(el)));
// OR
// Main array
let myArray = ["a", "b", "c", "d", "e", "f", "g"];
// Array to remove
const toRemove = ["b", "c", "g"];
const diff = () => (myArray = myArray.filter((el) => !toRemove.includes(el)));
console.log(diff()); // [ 'a', 'd', 'e', 'f' ]
// OR
const diff2 = () => {
return myArray = myArray.filter((el) => !toRemove.includes(el));
};
console.log(diff2()); // [ 'a', 'd', 'e', 'f' ]
A High performance and immutable solution
Javascript
const excludeFromArr = (arr, exclude) => {
const excludeMap = exclude.reduce((all, item) => ({ ...all, [item]: true }), {});
return arr.filter((item) => !excludeMap?.[item]);
};
Typescript:
const excludeFromArr = (arr: string[], exclude: string[]): string[] => {
const excludeMap = exclude.reduce<Record<string, boolean>>((all, item) => ({ ...all, [item]: true }), {});
return arr.filter((item) => !excludeMap?.[item]);
};

Convert flat array [k1,v1,k2,v2] to object {k1:v1,k2:v2} in JavaScript?

Is there a simple way in javascript to take a flat array and convert into an object with the even-indexed members of the array as properties and odd-indexed members as corresponding values (analgous to ruby's Hash[*array])?
For example, if I have this:
[ 'a', 'b', 'c', 'd', 'e', 'f' ]
Then I want this:
{ 'a': 'b', 'c': 'd', 'e': 'f' }
The best I've come up with so far seems more verbose than it has to be:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
for (var i = 0, len = arr.length; i < len; i += 2) {
obj[arr[i]] = arr[i + 1];
}
// obj => { 'a': 'b', 'c': 'd', 'e': 'f' }
Is there a better, less verbose, or more elegant way to do this? (Or I have just been programming in ruby too much lately?)
I'm looking for an answer in vanilla javascript, but would also be interested if there is a better way to do this if using undercore.js or jQuery. Performance is not really a concern.
Pretty sure this will work and is shorter:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
while (arr.length) {
obj[arr.shift()] = arr.shift();
}
See shift().
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = arr.reduce( function( ret, value, i, values ) {
if( i % 2 === 0 ) ret[ value ] = values[ i + 1 ];
return ret;
}, { } );
If you need it multiple times you can also add a method to the Array.prototype:
Array.prototype.to_object = function () {
var obj = {};
for(var i = 0; i < this.length; i += 2) {
obj[this[i]] = this[i + 1];
}
return obj
};
var a = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
a.to_object(); // => { 'a': 'b', 'c': 'd', 'e': 'f' }
You could first chunk your array into groups of two:
[['a', 'b'], ['c', 'd'], ['e', 'f']]
so that is is in a valid format to be used by Object.fromEntries(), which will build your object for you:
const chunk = (arr, size) => arr.length ? [arr.slice(0, size), ...chunk(arr.slice(size), size)] : [];
const arr = ['a', 'b', 'c', 'd', 'e', 'f'];
const res = Object.fromEntries(chunk(arr, 2));
console.log(res); // {a: "b", c: "d", e: "f"}
With underscore.js and lodash, you don't need to implement the chunk() method yourself, and can instead use _.chunk(), a method built into both libraries. The full lodash equivalent of the above would be:
// lodash
> _.fromPairs(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}
Using _.fromPairs provides better browser support, so if using lodash, it is preferred over Object.fromEntries()
Similarly, we can use _.object() if you're using underscore.js to build the object:
// underscore.js
> _.object(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}

Categories

Resources