Convert js object array into associative array - javascript

By using array.push() I'm updating a following array. I want to add index/key to every object in the object array as I want to check is a record exist with same index/key before pushing new item.
My array is like
$data = [
{
"id": 37,
"permit_id": 1,
"document_description": "zzxc",
"file_name": "zxc"
},
{
"permit_id": "1",
"document_description": "aa",
"file_name": "az"
},
{
"permit_id": "1",
"document_description": "aax",
"file_name": "azx"
}
]
and i want to convert this like
[
0 => {
"id": 37,
"permit_id": 1,
"document_description": "zzxc",
"file_name": "zxc"
},
1 => {
"permit_id": "1",
"document_description": "aa",
"file_name": "az"
},
2 => {
"permit_id": "1",
"document_description": "aax",
"file_name": "azx"
}
]
Is there any way to do this? please give me an idea.
Thank you!

There's no such thing as an associative array in JS. You need to convert it to an object.
You can use spread operator to convert the array to an object: let myObj = {...$data}
let $data=[{id:37,permit_id:1,document_description:"zzxc",file_name:"zxc"},{permit_id:"1",document_description:"aa",file_name:"az"},{permit_id:"1",document_description:"aax",file_name:"azx"}];
let myObj = {...$data}
console.log(myObj);
Update
If you want to search the array to check if an object with a property already exists, you can use Array.some()
let $data=[{id:37,permit_id:1,document_description:"zzxc",file_name:"zxc"},{permit_id:"1",document_description:"aa",file_name:"az"},{permit_id:"1",document_description:"aax",file_name:"azx"}];
let existingObj = {id:37,permit_id:1,document_description:"zzxc",file_name:"zxc"}
let nonexistingObj = {id:38,permit_id:1,document_description:"foo",file_name:"bar"}
if(!$data.some(item => item.id === existingObj.id)){
$data.push(existingObj)
console.log(`ID: ${existingObj.id} pushed`);
}else{
console.log(`ID: ${existingObj.id} already exists!`);
}
if(!$data.some(item => item.id === nonexistingObj.id)){
$data.push(nonexistingObj)
console.log(`ID: ${nonexistingObj.id} pushed`);
}else{
console.log(`ID: ${nonexistingObj.id} already exists!`);
}
console.log($data);

That is basically what you have already. The array of objects is effectively an associative array where the keys are integers - both extend Object.

You can use a forEach loop. Array cannot have key and value pairs like objects so an extra object has to be made so as to keys the values with numbered keys
var x=[
{
"id": 37,
"permit_id": 1,
"document_description": "zzxc",
"file_name": "zxc"
},
{
"permit_id": "1",
"document_description": "aa",
"file_name": "az"
},
{
"permit_id": "1",
"document_description": "aax",
"file_name": "azx"
}
]
var obj={};
x.forEach((e,j)=>{
obj[j+'=>']=e;
})
x=[obj]
console.log(x)

Related

How to convert an array of objects into an array with one object with the key being fixed and value being all original objects?

I have an array like so with each array item being an object and there can be multiple objects:
originalArray = [
{
"category": "ASDGFVFG",
"total": 1
},
{
"category": "DFGH",
"total": 1
},
.........
]
How can I convert it into the following structure? Note that categoryAndValueItems is fixed, so it can be 'hard-coded'.
newData = [{
categoryAndValueItems: [
{
"category": "ASDGFVFG",
"total": 1
},
{
"category": "DFGH",
"total": 1
},
.........
]
}]
I know that I can use .map to create a new array using values in an original array like so:
newArray = originalArray.map(x => ({....}))
I also know that I can use the dot notation or the square bracket notation to create a new key:
obj["categoryAndValueItems"] = ...
However, I'm unsure of how to go further or combine the two, how would I be able to convert the array?
Perhaps you're over-thinking it? It doesn't look like you're converting the array into anything, just setting it as a property on the new object as-is:
let newData = [{ categoryAndValueItems: originalArray }];
I have created a simple snippet, i hope this is what you were looking for...
const originalArray = [
{
"category": "ABC",
"total": 1
},
{
"category": "DEF",
"total": 2
},
{
"category": "GHI",
"total": 3
},
]
let newData = [{ categoryAndValueItems: originalArray }];
console.log(newData)

Getting the key in every JSON object

I am fairly new to Vue and JS but I am making API calls and getting a JSON response then sending the response to an empty array. How do I get the ID of each object in the array?
The array that the response is being pushed to is structured like this
groups: [
{
"id": "0",
"name": "a",
"price": 5
},
{
"id": "1",
"name": "b",
"price": 5
},
{
"id": "2",
"name": "c",
"price": 5
}
]
I'd like to pull the Id of each object and push the values to an empty array
for(var group in this.groups) {
if (this.groups.hasOwnProperty(0)) {
this.group = this.groups[0];
this.groupsId.push(this.innerObj);
}
}
The error I'm getting is saying Cannot read property '0' of undefined at eval
Ideally I'd like an array that has all the Ids of each object.
this.groups.hasOwnProperty(0) should be group.hasOwnProperty('id')
Use Array.prototype.map() to iterate over an array of objects and collect every ID into a new array:
const res = {
groups: [{
"id": "0",
"name": "a",
"price": 5
},
{
"id": "1",
"name": "b",
"price": 5
},
{
"id": "2",
"name": "c",
"price": 5
}
]
};
const ids = res.groups.map(obj => { // you use this.groups
if(obj.hasOwnProperty('id')) return obj.id;
});
console.log(ids)
There is the Array.map() method:
this.groupsId = this.groups.map(i => i.id);
If you already have elements in this.groupsId you can append the ids using Array.concat():
this.groupsId = this.groupsId.concat(this.groups.map(i => i.id));
You can use Array.prototype.reduce to loop and check if there's id.
const groups = [
{"name": "a","price": 5},
{"id": "1","name": "b","price": 5},
{ "id": "2","name": "c","price": 5}
];
const list = groups.reduce((groupIds, group) => group.id ? [...groupIds, group.id] : groupIds, []);
console.log(list);

How to loop through an array of object literals, concatenating values that share a duplicate id? [duplicate]

This question already has answers here:
Merge JavaScript objects in array with same key
(15 answers)
Closed 4 years ago.
I need an efficient way to loop through an array of object literals and concatenate values within the objects that have duplicate IDs.
Is there a more elegant way of doing this versus having multiple for loops nested within each other?
For example, this is the data I am given:
{ "theList": [
{
"id": 101,
"name": "Bubbles' Cat Farm",
"number": "123"
},
{
"id": 102,
"name": "Sunnyvale Park",
"number": "456"
},
{
"id": 101,
"name": "Bubbles' Cat Farm",
"number": "789"
]};
The expected result should be:
{ "theList": [
{
"id": 101,
"name": "Bubbles' Cat Farm",
"number": "123, 789"
},
{
"id": 102,
"name": "Sunnyvale Park",
"number": "456"
]}
You can use reduce
let obj = [{ "id": 101,"name": "Bubbles' Cat Farm","number": "123"},{"id": 102,"name": "Sunnyvale Park","number": "456"},{"id": 101,"name": "Bubbles' Cat Farm","number": "789"}];
let op = obj.reduce((out,inp)=>{
if(out[inp.id]){
out[inp.id].number += ', ' + inp.number;
} else {
out[inp.id] = inp
}
return out
},{})
console.log(Object.values(op))
using reduce and the findIndex function you will be able to achieve what you want.
const array = [{
"id": 101,
"name": "Bubbles' Cat Farm",
"number": "123"
},
{
"id": 102,
"name": "Sunnyvale Park",
"number": "456"
},
{
"id": 101,
"name": "Bubbles' Cat Farm",
"number": "789"
}
]
const result = array.reduce((accum, cv) => {
const index = accum.findIndex(item => item.id === cv.id);
if (index === -1) {
accum.push(cv);
} else {
accum[index].number += ", " + cv.number;
}
return accum;
}, [])
console.log(result)
If number is the only key which has distinct values, then you could do something like this using reduce:
const input = {"theList":[{"id":101,"name":"Bubbles' Cat Farm","number":"123"},{"id":102,"name":"Sunnyvale Park","number":"456"},{"id":101,"name":"Bubbles' Cat Farm","number":"789"}]}
const merged = input.theList.reduce((acc, {id,name,number}) =>{
acc[id]
? acc[id]["number"] += ", " + number
: acc[id] = {id,name,number};
return acc
},{})
const final = { "theList": Object.values(merged) }
console.log(final)
Create an accumulator with each unique id as key and the object you need in the final array as value like this. Then concatenate the number when a id already exists in the accumulator, else add a new key to the accumulator.
{
"101": {
"id": 101,
"name": "Bubbles' Cat Farm",
"number": "123, 789"
}
}
Then use Object.values to get only the values of theList in an array.
You can make your container a dictionary where the key is the ID and eachvalue is an empty list. So when you loop through the original data. If the key doesnt exist, create a list with one item. If the key does exist already, just append the value to the list.

Filter nested array in object array by array of values

Considering below object array:
[
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 1,
"name": "foo",
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 2,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
},
{
"guid": "jHab6i",
"courses": [
{
"id": 4,
"name": "foobar",
}
]
},
{...}
]
I am trying to filter an object array, comparing IDs in the nested courses array with in the below array:
filter.courses = [1,3]
The following line works for the nth value in the array: (via https://stackoverflow.com/a/41347441/9766768)
let fil = filter(this.results, { courses: [{ id: this.filter.courses[n] }]});
However, I'm hoping to achieve this (pseudo code below):
let fil = filter(this.results, { courses: [{ id: this.filter.courses }]});
Expected output would be an array of objects containing any of the course IDs elements, in this case:
[
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 1,
"name": "foo",
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 2,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
}
]
What would be considered the best solution in this case? Avoiding loops would be a bonus.
If you're trying to filter the elements whose course IDs contain in the filter.courses, you may use Array#every and Array#includes to do that:
const data = [{"guid":"j5Dc9Z","courses":[{"id":3,"name":"foo"}]},{"guid":"a5gdfS","courses":[{"id":1,"name":"bar"},{"id":3,"name":"foo"}]},{"guid":"jHab6i","courses":[{"id":7,"name":"foobar"}]}];
const courses = [1, 6, 3];
const r = data.filter(d => d.courses.every(c => courses.includes(c.id)));
console.log(r);
try this,
results = [
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 3,
"name": "foo",
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 1,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
}
]
var filter = [1]
console.log(results.map(result=>{
result.courses = result.courses.filter(course=>(filter.includes(course.id)))
return result
}))
Explore my recursive solution there: Playground Link
With this solution can nested array of objects being filtered from top level to botton level, layer by layer.
From what I understand the resulting array should contain all objects, that contain at least one course with an id that is contained in the array we use to filter.
So if an object exists with 2 courses - and one of them has an id we are looking for this object should then be part of the array that gets returned (see object with property "guid" : "a5gdfS" in the questions example)
With one little tweak the code provided in the answer by 31piy (marked as best by question owner) will do exactly what we desire. To do so we just change the array method every() to the array method some().
const r = data.filter(d => d.courses.every(c => courses.includes(c.id)));
const r = data.filter(d => d.courses.some(c => courses.includes(c.id)));
With the method every() the resulting array will only contain the objects, where each and every course has an id we are looking for. ("guid": "a5gdfS" is not in the resulting array)
With the method some() the resulting array will contain the objects, where at least one course has an id we are looking for ("guid": "a5gdfS" is in the resulting array)
/* arrays are the same as provided in the question
so that we can check against expected/desired output in the question */
const data = [{
"guid": "j5Dc9Z",
"courses": [{
"id": 1,
"name": "foo",
}]
},
{
"guid": "a5gdfS",
"courses": [{
"id": 2,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
},
{
"guid": "jHab6i",
"courses": [{
"id": 4,
"name": "foobar",
}]
}
];
const courses = [1, 3];
//array contains all objects with at least 1 course that has an id we are looking for
const r = data.filter(d => d.courses.some(c => courses.includes(c.id)));
console.log("code with some " + JSON.stringify(r));
//array contains only objects, whose classes all have an id we are looking for
const o = data.filter(d => d.courses.every(c => courses.includes(c.id)));
console.log("code with every " + JSON.stringify(o));
depending on what we are trying to do either every() or some() might be correct - depends on what we are trying to achieve

How can I get the result with underscore.js filter?

Here is the test array:
var test = [
{
"id": 1,
"team": [
{
"name": "Alex",
"age": 27,
"checked": true
},
{
"name": "Bob",
"age": 35,
"checked": false
}
],
"checked": true
},
{
"id": "2",
"team": [
{
"name": "Jack",
"age": 37,
"checked": false
},
{
"name": "Tom",
"age": 29,
"checked": true
}
],
"checked": true
}];
And the result that I want to get is an array like this:
result = ["Alex", "Tom"];
The result array contains all items that the "checked" attribute equals to true in team.
I try to get the result with the underscore.js filter, but I cannot get the correct result.
If you have a better solution, please tell me.
Here is my code:
_.filter(test, function(team) {
_.filter(team, function(worker){
if(worker.checked)
return worker.name;
});});
Here's how you can do it in both underscore and lodash:
Underscore jsfiddle:
var result = _.chain(test).pluck('team').flatten().filter({checked:true}).value();
Lodash jsfiddle:
var result = _(test).pluck('team').flatten().filter({checked:true}).value();
Take the team arrays together, flatten them so you have the nested arrays, filter on the property and the result are the objects containing the name and checked being true. If you want just the names, do another pluck.
Here's an underscorejs version with a shorter filter and just giving back the names:
var result = _.chain(test).pluck('team').flatten().filter('checked').pluck('name').value();
// ["Alex", "Tom"]
You can simply use forEach function to handle this
var test = [...];
var result = [];
test.forEach(function(item) {
item.team.forEach(function(worker) {
if(worker.checked) {
result.push(worker.name);
}
})
})
console.log(result)
//Return ["Alex","Tom"]
One way to use filtering for multidimentional array is by using filter and any.
_.filter(test, function(team) {
return _.any(team.team, function(player) {
return player.checked;
});
});

Categories