Create object array by pushing variables? - javascript

I am trying to create something like
var[1] = {object1, object2};
var[2] = {object1, object3);
Or something like that so that I can loop over each result and get all the objects associated with that key. The problem is I am either really tried or something because I can't seem to figure out how to do that.
In PHP I would do something like
$var[$object['id']][] = object1;
$var[$object['id']][] = object2;
How can I do something like that in Javascript?
I have a list of object elements, that have a key value called id and I want to organize them all by ID. Basically...
[0] = { id: 2 },
[1] = { id: 3 },
[2] = { id: 2 },
[3] = { id: 3 }
And I want to have them organized so it is like
[0] = { { id: 2 }, { id: 2 } }
[1] = { { id: 3 }, { id: 3} }

var indexedArray = [];
for(var key in myObjects) {
var myObject = myObjects[key];
if(typeof(indexedArray[myObject.id]) === 'undefined') {
indexedArray[myObject.id] = [myObject];
}
else {
indexedArray[myObject.id].push(myObject);
}
}
console.log(indexedArray);
http://jsfiddle.net/2fr4k/

Array is defined by square brackets:
var myArray = [{ "id": 2 }, { "id": 3 }];
What you had is not a valid syntax.

Using ECMA5 methods, you could do something like this.
Javascript
var d1 = [{
id: 2
}, {
id: 3
}, {
id: 2
}, {
id: 3
}],
d2;
d2 = d1.reduce(function (acc, ele) {
var id = ele.id;
if (!acc[id]) {
acc[id] = [];
}
acc[id].push(ele);
return acc;
}, {});
d2 = Object.keys(d2).map(function (key) {
return this[key];
}, d2);
console.log(JSON.stringify(d2));
Output
[[{"id":2},{"id":2}],[{"id":3},{"id":3}]]
On jsFiddle

Related

adding another key and value to an object inside an array with JS

So I currently have a bunch of objects inside an array like below. However, I'm now trying to write a function that allows me to add another key|value into the object that was added last.
My current idea is using the arrayname.length - 1 to work out the position of the object within the array.
Would I need to create a temporary array to store the new object and then set (tempArray = oldArray) at the end of the function or would I concatinate them both?
const state = [
{
userId: 1,
},
{
Name: name,
},
{
age: 52,
},
{
title: "et porro tempora",
}]
this is the current code
let objects = [];
const addParent = (ev) =>{
ev.preventDefault();
// getting the length of the objects array
let arrayLength = objects.length;
// if the length of the array is zero - empty or one then set it to default zero
// else if there is objects stored in the array minus 1 to get the array position
if(arrayLength <= 0){
arrayLength = 0;
}else{
arrayLength = objects.length - 1;
}
//make a temporary array to be able to push new parent into an existing object
var tempObjects = []
for (var index=0; index<objects.length; index++){
}
//create a new parent object key : value
let parent = {
key: document.getElementById('key').value,
value: document.getElementById('value').value
}
//push parent object key and value into object
//objects.push(parent);
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn1').addEventListener('click', addParent);
});
There are multiple ways to do this.
Try this one
var objects = [{
name: "1"
}];
const addParent = (ev) => {
let parent = {
key: "some value",
value: "some value"
}
objects = Array.isArray(objects) ? objects : [];
let lastObjectIndex = objects.length - 1;
lastObjectIndex = lastObjectIndex > -1 ? lastObjectIndex : 0
objects[lastObjectIndex] = { ...objects[lastObjectIndex],
...parent
}
}
I think You want to add new value to last object of the array
Method 1
const state = [
{
userId: 1,
},
{
Name: name,
},
{
age: 52,
},
{
title: "et porro tempora",
}]
state[state.length - 1].newKey = "value"
console.log(state)
Method 2
const state = [
{
userId: 1,
},
{
Name: name,
},
{
age: 52,
},
{
title: "et porro tempora",
}]
// 1st method
state[state.length - 1] = {
...state[state.length - 1] ,
newKey : "value"
}
console.log(state)
You can probably use something like this:
const a = [
{ "a" : "a" },
{ "b" : "b" }
]
const c = a.map((obj, index) => {
if (index === a.length -1) {
return { ...obj, newProp: "newProp" }
}
return obj;
});
console.log(c)
This will add property on the last object using spread operator, you can look it up if you are new to JS but basically it will retain all the existing property and add the newProp to the object

How to add label to js array?

Hi I am looking to create an array that looks similar to this
const userList = {
123: "Tom",
124: "Michael",
125: "Christin",
};
it contains both value and label, what I tried so far
let raw = []
for (let x in data) {
raw.push(data[x].facility_name : data[x].id)
}
but it didn't work because "," was expected, if someone can help please
You are confusing arrays and objects. You need to add a key to an object not push. I kept it as a for in loop, but a for of loop would make more sense.
const data = [
{ id: 1, facility_name: "foo1" },
{ id: 2, facility_name: "foo2" },
{ id: 3, facility_name: "foo3" }
];
let raw = {};
for (let x in data) {
raw[data[x].id] = data[x].facility_name;
}
console.log(raw);
How I would code it using reduce.
var data = [
{ id: 1, facility_name: "foo1" },
{ id: 2, facility_name: "foo2" },
{ id: 3, facility_name: "foo3" }
];
const raw = data.reduce(function (acc, facility) {
acc[facility.id] = facility.facility_name;
return acc;
}, {})
console.log(raw);
IF your data has nested objects then you might do this:
let raw = {};
for(x in data)
{
raw[data[x].facility_name] = data[x].id;
}
This is useful when you want to get rid of duplicates.

Create unique values from duplicates in Javascript array of objects

I have an array of duplicated objects in Javascript. I want to create an array of unique objects by adding the index of occurrence of the individual value.
This is my initial data:
const array= [
{name:"A"},
{name:"A"},
{name:"A"},
{name:"B"},
{name:"B"},
{name:"C"},
{name:"C"},
];
This is expected end result:
const array= [
{name:"A-0"},
{name:"A-1"},
{name:"A-2"},
{name:"B-0"},
{name:"B-1"},
{name:"C-0"},
{name:"C-1"},
];
I feel like this should be fairly simple, but got stuck on it for a while. Can you please advise how I'd go about this? Also if possible, I need it efficient as the array can hold up to 1000 items.
EDIT: This is my solution, but I don't feel like it's very efficient.
const array = [
{ name: "A" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
const sortedArray = _.sortBy(array, 'name');
let previousItem = {
name: '',
counter: 0
};
const indexedArray = sortedArray.map((item) => {
if (item.name === previousItem.name) {
previousItem.counter += 1;
const name = `${item.name}-${previousItem.counter}`;
return { name };
} else {
previousItem = { name: item.name, counter: 0};
return item;
}
});
Currently you are sorting it first then looping over it, which may be not the most efficient solution.
I would suggest you to map over it with a helping object.
const a = [{name:"A"},{name:"A"},{name:"A"},{name:"B"},{name:"B"},{name:"C"},{name:"C"},], o = {};
const r = a.map(({ name }) => {
typeof o[name] === 'number' ? o[name]++ : o[name] = 0;
return { name: `${name}-${o[name]}` };
});
console.log(r);
Keep a counter, and if the current name changes, reset the counter.
This version mutates the objects. Not sure if you want a copy or not. You could potentially sort the array by object name first to ensure they are in order (if that's not already an existing precondition.)
const array = [
{ name: "A" },
{ name: "A" },
{ name: "A" },
{ name: "B" },
{ name: "B" },
{ name: "C" },
{ name: "C" },
];
let name, index;
for (let i in array) {
index = array[i].name == name ? index + 1 : 0;
name = array[i].name;
array[i].name += `-${index}`;
}
console.log(array);
Another way, if you don't want to sort, and don't want to mutate any objects, is to use a map and keep track of the current index for each object.
const array = [
// NOTE: I put the items in mixed up order.
{ name: "A" },
{ name: "C" },
{ name: "A" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
let index = {};
let next = name => index[name] = index[name] + 1 || 0;
let result = array.map(obj => ({ ...obj, name: obj.name + '-' + next(obj.name) }));
console.log(result);

Finding objects in a nested array along with their position

I've taken the following sample from a different question. And I am able to identify the object. But I also need to find our the position of that object. For example:
var arr = [{
Id: 1,
Categories: [{
Id: 1
},
{
Id: 2
},
]
},
{
Id: 2,
Categories: [{
Id: 100
},
{
Id: 200
},
]
}
]
If I want to find the object by the Id of the Categories, I can use the following:
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
However, I also need to know the position of the object in the array. For example, if we are looking for object with Id = 100, then the above code will find the object, but how do I find that it's the second object in the main array, and the first object in the Categories array?
Thanks!
Well, if every object is unique (only in one of the categories), you can simply iterate over everything.
var arr = [{
Id: 1,
Categories: [{Id: 1},{Id: 2}]
},
{
Id: 2,
Categories: [{Id: 100},{Id: 200}]
}
];
var needle = 100;
var i = 0;
var j = 0;
arr.forEach(function(c) {
c.Categories.forEach(function(e) {
if(e.Id === needle) {
console.log("Entry is in position " + i + " of the categories and in position " + j + " in its category.");
}
j++;
});
j = 0;
i++;
});
function findInArray(needle /*object*/, haystack /*array of object*/){
let out = [];
for(let i = 0; i < haystack.lenght; i++) {
if(haystack[i].property == needle.property) {
out = {pos: i, obj: haystack[i]};
}
}
return out;
}
if you need the position and have to filter over an property of the object you can use a simple for loop. in this sample your result is an array of new object because there can be more mathches than 1 on the value of the property.
i hope it helps
Iterate over the array and set index in object where match found
var categoryGroups = [{
Id : 1,
Categories : [{
Id : 1
}, {
Id : 2
},
]
}, {
Id : 2,
Categories : [{
Id : 100
}, {
Id : 200
},
]
}
]
var filterVal = [];
var needle = 100;
for (var i = 0; i < categoryGroups.length; i++) {
var subCategory = categoryGroups[i]['Categories'];
for (var j = 0; j < subCategory.length; j++) {
if (subCategory[j]['Id'] == findId) {
filterVal.push({
catIndex : i,
subCatIndex : j,
id : needle
});
}
}
}
console.log(filterVal);
Here is solution using reduce:
var arr = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }, ] } ]
const findPositions = (id) => arr.reduce((r,c,i) => {
let indx = c.Categories.findIndex(({Id}) => Id == id)
return indx >=0 ? {mainIndex: i, categoryIndex: indx} : r
}, {})
console.log(findPositions(100)) // {mainIndex: 1, categoryIndex: 0}
console.log(findPositions(1)) // {mainIndex: 0, categoryIndex: 0}
console.log(findPositions(200)) // {mainIndex: 1, categoryIndex: 1}
console.log(findPositions(0)) // {}
Beside the given answers with fixt depth searh, you could take an recursive approach by checking the Categories property for nested structures.
function getPath(array, target) {
var path;
array.some(({ Id, Categories = [] }) => {
var temp;
if (Id === target) {
path = [Id];
return true;
}
temp = getPath(Categories, target);
if (temp) {
path = [Id, ...temp];
return true;
}
});
return path;
}
var array = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 },] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }] }];
console.log(getPath(array, 100));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Create new array from iterating JSON objects and getting only 1 of its inner array

See jsfiddle here: https://jsfiddle.net/remenyLx/2/
I have data that contains objects that each have an array of images. I want only the first image of each object.
var data1 = [
{
id: 1,
images: [
{ name: '1a' },
{ name: '1b' }
]
},
{
id: 2,
images: [
{ name: '2a' },
{ name: '2b' }
]
},
{
id: 3
},
{
id: 4,
images: []
}
];
var filtered = [];
var b = data1.forEach((element, index, array) => {
if(element.images && element.images.length)
filtered.push(element.images[0].name);
});
console.log(filtered);
The output needs to be flat:
['1a', '2a']
How can I make this prettier?
I'm not too familiar with JS map, reduce and filter and I think those would make my code more sensible; the forEach feels unnecessary.
First you can filter out elements without proper images property and then map it to new array:
const filtered = data1
.filter(e => e.images && e.images.length)
.map(e => e.images[0].name)
To do this in one loop you can use reduce function:
const filtered = data1.reduce((r, e) => {
if (e.images && e.images.length) {
r.push(e.images[0].name)
}
return r
}, [])
You can use reduce() to return this result.
var data1 = [{
id: 1,
images: [{
name: '1a'
}, {
name: '1b'
}]
}, {
id: 2,
images: [{
name: '2a'
}, {
name: '2b'
}]
}, {
id: 3
}, {
id: 4,
images: []
}];
var result = data1.reduce(function(r, e) {
if (e.hasOwnProperty('images') && e.images.length) r.push(e.images[0].name);
return r;
}, [])
console.log(result);
All answers are creating NEW arrays before projecting the final result : (filter and map creates a new array each) so basically it's creating twice.
Another approach is only to yield expected values :
Using iterator functions
function* foo(g)
{
for (let i = 0; i < g.length; i++)
{
if (g[i]['images'] && g[i]["images"].length)
yield g[i]['images'][0]["name"];
}
}
var iterator = foo(data1) ;
var result = iterator.next();
while (!result.done)
{
console.log(result.value)
result = iterator.next();
}
This will not create any additional array and only return the expected values !
However if you must return an array , rather than to do something with the actual values , then use other solutions suggested here.
https://jsfiddle.net/remenyLx/7/

Categories

Resources