How can I remove the parent keys from a javascript Object? - javascript

I currently have this Object:
schoolsObject = [{
"college_1":
{
"id":"college_1",
"location":"Victoria",
"name":"College One"
},
"college_2":
{
"id":"college_2",
"location":"Tasmania",
"name":"College Two"
}
}];
I want to remove the top level keys ie. college_1, college_2 and 'flatten' the object out like this, so I have no 'top level' keys:
flatSchoolsObject =
[{
"id":"college_1",
"location":"Victoria",
"name":"College One"
},
{
"id":"college_2",
"location":"Tasmania",
"name":"College Two"
}];
Here is my latest attempt, I've made a lot of different try's but have not been documenting them:
// schoolIDs = Object.keys(schoolsObject);
var schools = {};
for(var i=0; i<Object.keys(schoolsObject).length; i++){
for (var property in schoolsObject) {
if (schoolsObject.hasOwnProperty(property)) {
schools[i] = {
'id': schoolsObject[property]['id'],
'name' : schoolsObject[property]['name'],
'location': schoolsObject[property]['location'],
};
}
}
}
console.log(schools)
Obviously this one is not what I'm after as it leaves me with Object {0: Object, 1: Object}.
Is what I want to do here possible or am I looking at it the wrong way?

Given Object:
schoolsObject = [{
"college_1":{
"id":"college_1",
"location":"Victoria",
"name":"College One"
},
"college_2":{
"id":"college_2",
"location":"Tasmania",
"name":"College Two"
}
}];
Solution:
Object.values(schoolsObject[0]);
Result:
[{
"id":"college_1",
"location":"Victoria",
"name":"College One"
},{
"id":"college_2",
"location":"Tasmania",
"name":"College Two"
}]

(Codewise) simplest solution could be using a combination of Object.keys() and Array.map():
flatSchoolsObject = Object.keys( schoolsObject[0] )
.map( ( key ) => schoolsObject[0][ key ] );
If the schoolsObject array has more entries, the code would have to be slightly adjusted:
let step1 = schoolsObject.map( ( el ) => {
return Object.keys( schoolsObject[0] )
.map( ( key ) => schoolsObject[0][ key ] );
})
flatSchoolsObject = [].concat.apply( [], step1 );
(the step1 variable is just introduced for readability reasons.)

You need to concat the result of extracting values from each item in schoolObject
flatSchoolsObject = [].concat.call(
schoolsObject.map(function(item) {
return Object.keys(item).map(function(key) {
return item[key];
})
})
)
or using Array.prototype.reduce
flatSchoolsObject = schoolsObject.reduce(function(acc, item) {
return acc.concat(Object.keys(item).map(function(key){
return item[key]
})
}, [])

You can use Array#map on the result of Object.keys to do it. Since you have just a single object in the array, we do it like this:
schoolsObject = Object.keys(schoolsObject[0]).map(function(key) {
return schoolsObject[0][key];
});
Live example:
var schoolsObject = [
{
"college_1": {
"id": "college_1",
"location": "Victoria",
"name": "College One"
},
"college_2": {
"id": "college_2",
"location": "Tasmania",
"name": "College Two"
}
}];
schoolsObject = Object.keys(schoolsObject[0]).map(function(key) {
return schoolsObject[0][key];
});
console.log(schoolsObject);
With ES2015+ you could use an arrow function to make that shorter:
schoolsObject = Object.keys(schoolsObject[0]).map(key => schoolsObject[0][key]);

// Code goes here
var schoolsObject = [{
"college_1":
{
"id":"college_1",
"location":"Victoria",
"name":"College One"
},
"college_2":
{
"id":"college_2",
"location":"Tasmania",
"name":"College Two"
}
}];
var result = Object.keys(schoolsObject[0]).map(function(key){
return schoolsObject[0][key];
})
console.log(result);
other version
var schoolsObject = [{
"college_1": {
"id": "college_1",
"location": "Victoria",
"name": "College One"
},
"college_2": {
"id": "college_2",
"location": "Tasmania",
"name": "College Two"
}
}];
var result = [];
for (var property in schoolsObject[0]) {
if (schoolsObject[0].hasOwnProperty(property)) {
result.push(schoolsObject[0][property]);
}
}
console.log(result);

Related

filtering list by multiple conditions

there is a list of users
filterData = [
{
"position":"lawyer",
"department_positions":[],
"group_positions":[
{"group":{"id":2,"code":"234","name":"group1"},"lead":false},
{"group":{"id":1,"code":"123","name":"group12"},"lead":true}
]
},
{
"position":"director",
"department_positions":[
{"department":{"id":3,"code":"333","name":"subDep"},"lead":false}
],
"group_positions":[
{"group":{"id":2,"code":"234","name":"group1"},"lead":false},
{"group":{"id":1,"code":"123","name":"group12"},"lead":true}
]
},
{
"position":"director",
"department_positions":[],
"group_positions":[]
}
]
and list of filters
categories = {
"position":["lawyer","director"],
"group_positions":["group1","group12"],
"department_positions":["generalDep", "subDep"]
}
It is necessary to filter users taking into account the fact that several filters can be selected at the same time. For example, i want to find user with position = "director" and AND group_positions = "group1" AND department_positions = "subDep"
my code doesn't allow filtering by multiple conditions. how can i fix it?
this.filter = this.filterData.filter(item => {
for (let key in this.categories) {
if (item[key].find(el =>
this.categories[key].includes(
el.group?.name || el.department?.name
)
)) {
return true
}
}
return false
})}
This is a good place to employ an es6 class to give behavior to the object being filtered. Augment each object to determine if it matches the "category" object.
(from the example data, this assumes the OP is looking for a "product of sums" match: for all of the category keys match at least one of the category values)
class FilterMe {
constructor(item) {
Object.assign(this, item);
}
namesForKey(key) {
switch (key) {
case 'position':
return [this.position]; // always answer an array
case 'group_positions':
return this.group_positions.map(gp => gp.group.name);
case 'department_positions':
return this.department_positions.map(dp => dp.department.name);
default:
return [];
}
}
// return true if a single filter key-value pair is matched
matchesFilterKeyValue(filterKey, filterOptions) {
const myNames = this.namesForKey(filterKey);
const matches = filterOptions.filter(e => myNames.includes(e));
return matches.length > 0;
}
// return true if all filter key-values pairs are matched
matchesFilter(filter) {
return Object.entries(filter).every(keyValue => {
return this.matchesFilterKeyValue(...keyValue);
})
}
}
const filterData = [{
"position": "lawyer",
"department_positions": [],
"group_positions": [{
"group": {
"id": 2,
"code": "234",
"name": "group1"
},
"lead": false
}, {
"group": {
"id": 1,
"code": "123",
"name": "group12"
},
"lead": true
}]
},
{
"position": "director",
"department_positions": [{
"department": {
"id": 3,
"code": "333",
"name": "subDep"
},
"lead": false
}],
"group_positions": [{
"group": {
"id": 2,
"code": "234",
"name": "group1"
},
"lead": false
}, {
"group": {
"id": 1,
"code": "123",
"name": "group12"
},
"lead": true
}]
},
{
"position": "director",
"department_positions": [],
"group_positions": []
}
]
const categories = {
"position": ["lawyer", "director"],
"group_positions": ["group1", "group12"],
"department_positions": ["generalDep", "subDep"]
}
// convert the filterData to the objects and test them...
let objects = filterData.map(d => new FilterMe(d));
let matches = objects.filter(o => o.matchesFilter(categories))
console.log(matches)
You can try something like this:
let filtered = example.filter(item => {
let valid = false
if (item.includes('something')) {
valid = true
}
if (!valid) {
// check second condition
}
return valid
})
Use a temporary placeholder so you don't immediately have to return true/false.

Simple JavaScript Convert JSON format

I have a json format and want to convert
Here are my script. I had tried but cannot get the correct results. Please give some advice, thanks and appreciate.
function groupBy() {
var list = [{
"id": "009",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "007",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "006",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "pm1",
"Nm": "Model 1",
"pid": "puma"
},
{
"id": "003",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "pm5",
"Nm": "Model 1",
"pid": "puma"
},
{
"id": "aj1",
"Nm": "Model 1",
"pid": "nike"
},
{
"id": "aj2",
"Nm": "Model 1",
"pid": "nike"
}
];
var output = [];
for (var i = 0; i < list.length; i++) {
if (list[i].pid != undefined) {
output.push(list[i]);
}
}
console.log(output);
}
groupBy();
One option is to reduce into an object indexed by pids, whose values are arrays. On each iteration, create the array at the appropriate property if it doesn't exist, and then push to that array:
var list = [
{"id":"009","Nm":"Model 1","pid":"adidas"},
{"id":"007","Nm":"Model 1","pid":"adidas"},
{"id":"006","Nm":"Model 1","pid":"adidas"},
{"id":"pm1","Nm":"Model 1","pid":"puma"},
{"id":"003","Nm":"Model 1","pid":"adidas"},
{"id":"pm5","Nm":"Model 1","pid":"puma"},
{"id":"aj1","Nm":"Model 1","pid":"nike"},
{"id":"aj2","Nm":"Model 1","pid":"nike"}
];
console.log(
list.reduce((a, item) => {
const { pid } = item;
if (!a[pid]) a[pid] = [];
a[pid].push(item);
return a;
}, {})
);
You're pretty close there. But [] is to initialize an array instead of an object in javascript. In JS, it's {}.
Following is one of many ways you can accomplish this.
function groupBy() {
var list = [
{"id":"009","Nm":"Model 1","pid":"adidas"},
{"id":"007","Nm":"Model 1","pid":"adidas"},
{"id":"006","Nm":"Model 1","pid":"adidas"},
{"id":"pm1","Nm":"Model 1","pid":"puma"},
{"id":"003","Nm":"Model 1","pid":"adidas"},
{"id":"pm5","Nm":"Model 1","pid":"puma"},
{"id":"aj1","Nm":"Model 1","pid":"nike"},
{"id":"aj2","Nm":"Model 1","pid":"nike"}
];
// Initialize output as an object
var output = {};
for (var i = 0; i < list.length; i++){
// 'objectKey' is where you group the list item by its 'pid'
var objectKey = list[i].pid;
// If there's a 'pid' in the list item, but 'output' is not an array yet, then..
if (objectKey && !output.hasOwnProperty(objectKey)){
// Initialize output.group to be an array
output[ objectKey ] = [];
}
// Then finally, store the list into output's group that we created above.
output[ objectKey ].push( list[i] );
}
console.log(output);
}
groupBy();
Use this method for your any group by
const groupBy = function(arr, prop) {
return arr.reduce(function(groups, item) {
const val = item[prop]
groups[val] = groups[val] || []
groups[val].push(item)
return groups
}, {})
}
const list = [
{"id":"009","Nm":"Model 1","pid":"adidas"},
{"id":"007","Nm":"Model 1","pid":"adidas"},
{"id":"006","Nm":"Model 1","pid":"adidas"},
{"id":"pm1","Nm":"Model 1","pid":"puma"},
{"id":"003","Nm":"Model 1","pid":"adidas"},
{"id":"pm5","Nm":"Model 1","pid":"puma"},
{"id":"aj1","Nm":"Model 1","pid":"nike"},
{"id":"aj2","Nm":"Model 1","pid":"nike"}
];
const groupOutput = groupBy(list, 'pid');
You pass your key as second argument into groupBy for group by.

Merge two json arrays

I have to array i want to merge them in one array by same id. So every two array have same id should be merged
Case 1:
{
"id":1212,
"instructor":"william",
...
}
Case 2:
[
{
"id":1212,
"name":"accounting",
...
},
{
"id":1212,
"name":"finance",
...
}
]
I need the result to be :
{
"id": 1212,
"instructor": "william",
"Courses": [
{
"id":1212,
"name":"accounting",
...
},
{
"id":1212,
"name":"finance",
...
}
]
}
What you're asking isn't merging, but here is how you can do that.
const instructors = [{ "id":1212, "instructor":"william", }];
const courses = [
{ "id":1212, "name":"accounting" },
{ "id":1212, "name":"finance" }
];
const expected = [{ "id":1212, "instructor":"william", "courses": [
{ "id":1212, "name":"accounting" },
{ "id":1212, "name":"finance" }
]}];
const composed = instructors.map(ins => {
const ret = {...ins};
ret.courses = courses.filter(cou => cou.id === ins.id);
return ret;
});
console.log(composed);
var finArr;
var course = [];
use forEach loop javascript get all value in put your value instead of varid and varname
course.push({"id":varid,"name":varname});
finArr = {"id":variableId,"instructor":variablename,"Courses":course}

Build array from another array if some key are identical using JavaScript

I have an array of data. Some of the key in the array are same. I would like to create a new array based on the key and add the other data.
This is my array
var myObjOne = [
{
"name":"John",
"id":1,
"car":"maruti"
},
{
"name":"John",
"id":2,
"car":"wolks"
},
{
"name":"John",
"id":3,
"car":"bmw"
},
{
"name":"Peter",
"id":4,
"car":"alto"
},
{
"name":"Peter",
"id":5,
"car":"swift"
}
];
I would like to convert the array in to the below format.
var myObj = [
{
"name":"John",
"items": [
{ "id":1, "car":"maruti" },
{ "id":2, "car":"wolks" },
{ "id":3, "car":"bmw" }
]},
{
"name":"Peter",
"items": [
{ "id":4, "car":"alto" },
{ "id":5, "car":"swift" },
]
}
];
I am working on a node environment.
You can create an object using Array#reduce first which maps name with items, and then create the final array by looping over the intermediate map using a for...of loop:
var source = [{"name":"John","id":1,"car":"maruti"},{"name":"John","id":2,"car":"wolks"},{"name":"John","id":3,"car":"bmw"},{"name":"Peter","id":4,"cars":"alto"},{"name":"Peter","id":5,"cars":"swift"}];
const map = source.reduce((acc, {name, ...obj}) => {
if (!acc[name]) {
acc[name] = [];
}
acc[name].push(obj);
return acc;
}, {});
const result = [];
for (let[name, items] of Object.entries(map)) {
result.push({name, items});
}
console.log(result);
Array.reduce is at rescue.This method accepts an accumulator and current
item. Check in the accumulator if there exist an object where the value of name property is John or Peter
var myObjOne = [{
"name": "John",
"id": 1,
"car": "maruti"
},
{
"name": "John",
"id": 2,
"car": "wolks"
},
{
"name": "John",
"id": 3,
"car": "bmw"
},
{
"name": "Peter",
"id": 4,
"car": "alto"
},
{
"name": "Peter",
"id": 5,
"car": "swift"
}
];
var newObj = myObjOne.reduce(function(acc, curr, currIndex) {
// using findIndex to check if there exist an object
// where the value of the name property is John, Peter
// if it exist it will return the index else it will return -1
let ifNameExist = acc.findIndex(function(item) {
return item.name === curr.name;
})
// if -1 then create a object with name and item property and push
// it to the accumulator
if (ifNameExist === -1) {
let nameObj = {};
nameObj.name = curr.name;
nameObj.items = [];
nameObj.items.push({
id: curr.id,
car: curr.car
})
acc.push(nameObj)
} else {
// if such an object already exist then just update the item array
acc[ifNameExist].items.push({
id: curr.id,
car: curr.car
})
}
return acc;
}, []);
console.log(newObj)
Use .reduce to group by name, and use .find inside the reducer to find if the matching name has already been added:
const input=[{"name":"John","id":1,"car":"maruti"},{"name":"John","id":2,"car":"wolks"},{"name":"John","id":3,"car":"bmw"},{"name":"Peter","id":4,"cars":"alto"},{"name":"Peter","id":5,"cars":"swift"}]
const output = input.reduce((a, { name, ...item }) => {
const foundNameObj = a.find(nameObj => nameObj.name === name);
if (foundNameObj) foundNameObj.items.push(item);
else a.push({ name, items: [item] });
return a;
}, []);
console.log(output);

Create JSON Array dynamically from an object

I have an object A as shown below.
var A = {
"1": [ "1_1", "1_2", "1_3" ],
"2": [ "2_1", "2_2" ]
};
Need to build a new array dynamically using js. Suppose
object A key should map to attribute text of Array AA and value should be to children as given below.
var AA = [
{
"text": "1",
"state": "open",
"children": [
{ "text": "1_1" },
{ "text": "1_2" },
{ "text": "1_3" }
]
},
{
"text": "2",
"state": "open",
"children": [
{ "text": "2_1" },
{ "text": "2_2" }
]
}
];
This is my function but its not working as expected. Could someone pls help?
function constructJSONArr() {
var A = {
"1": [ "1_1", "1_2", "1_3" ],
"2": [ "2_1", "2_2" ]
};
for (var key in A) {
var tempArr = [];
tempArr.push(key);
for (var i = 0; i < key.length; i++) {
return {
'text': key,
'state': 'closed',
'children': A[key].map(function(child) {
return {
'text': child
};
})
}
}
}
}
When you return inside a function, the function ends and returns immediately. In your case, the return inside the for loop causes the function to return the 1st key object. To solve this, you need to create the objects and push them into an arr. You can return freely inside Array.map() because each iteration invokes a function.
Fixed solution:
Iterate with for...in. Get the key. Push a new object into arr. Use the key as the text property, the state, and children. To create the children get the array from the original object by the key, and use Array.map() to generate the child objects. Return arr.
var A = {
"1": ["1_1", "1_2", "1_3"],
"2": ["2_1", "2_2"]
};
function constructJSONArr(A) {
var arr = [];
for (var key in A) {
arr.push({
text: key,
state: 'closed',
children: A[key].map(function(t) {
return {
text: t
};
})
});
}
return arr;
}
var result = constructJSONArr(A);
console.log(result);
ESNext solution
Use Object.entries() to get keys and respective values from the object A. Iterate the entries with two nested Array.map() calls. The 1st to create the outer object, and the 2nd to create the children.
const A = {
"1": ["1_1", "1_2", "1_3"],
"2": ["2_1", "2_2"]
};
const constructJSONArr = (obj) =>
Object.entries(obj).map(([text, children]) => ({
text,
state: 'closed',
children: children.map((text) => ({
text
}))
}));
var result = constructJSONArr(A);
console.log(result);
You can use Object.keys() to iterate through the object and Array.map to create the new array.
var A = {
"1": ["1_1", "1_2", "1_3"],
"2": ["2_1", "2_2"]
};
var transformed = Object.keys(A).map(key => {
return {
text: key,
state: "open",
children: A[key].map(value => {
return {
text: value
};
})
};
});
console.log(transformed);

Categories