Converting array of objects into nested form - angularjs

I have an array of objects in this form
nnz=[{
"verb":"has",
"nouns": "employees"
},
{
"verb":"has",
"nouns": "managers"
},
{
"verb":"have",
"nouns": "departments"
}
]
but i want to convert it into this form
[ {
"verb":"has",
"nouns": ["employees", "managers"]
},
{
"verb":"have",
nouns:["departments"]
}
]
and this work has to be done from client side. I am working in node.js. I want to allow user to select multiple nouns against each verb and when user selects nouns against verb it should be saved into an array in the above given form. I am unable to figure it out how can i implement this logic.
Update: we have to check verb too.now it became more tricky.

You can do somethong like this, using some Array built-in functions:
const array = [
{
"verb":"has",
"nouns": "employees"
},
{
"verb":"has",
"nouns": "managers"
},
{
"verb":"has",
"nouns": "departments"
}
]
const aggregated = array.reduce( (arr, el) =>{
let found = arr.find(ll => ll.verb == el.verb);
if(found) found.nouns.push(el.nouns);
else arr.push({verb : el.verb, nouns : [el.nouns] })
return arr;
}, []);
console.log(aggregated);

First create a temporary object that uses the verb value as keys then iterate your existing data pushing nouns to corresponding array in that temporary object.
Then map the temporary object to a new array.
nnz = [{
"verb": "has",
"nouns": "employees"
}, {
"verb": "has",
"nouns": "managers"
}, {
"verb": "has",
"nouns": "departments"
}]
var tmp = {};
nnz.forEach(function(item) {
tmp[item.verb] = tmp[item.verb] || {
verb: item.verb,
nouns: []
};
tmp[item.verb].nouns.push(item.nouns);
});
var results = Object.keys(tmp).map(function(key) {
return tmp[key];
});
console.log(results);

Try these two approaches as per your requirement. I hope it will work as per the expectation .
First Approach :
When you know the property names :
var nnz = [{
"verb":"has",
"nouns": "employees"
},
{
"verb":"has",
"nouns": "managers"
},
{
"verb":"has",
"nouns": "departments"
}
];
var newObj = {};
var nouns = [];
for (var i in nnz) {
nouns.push(nnz[i].nouns);
newObj.verb = nnz[i].verb;
newObj.nouns = nouns;
}
nnz = newObj;
console.log(nnz);
Second Approach :
When you don't know the property names :
var nnz = [{
"verb":"has",
"nouns": "employees"
},
{
"verb":"has",
"nouns": "managers"
},
{
"verb":"has",
"nouns": "departments"
}
];
var newObj = {};
var nounsArr = [];
for (var i in nnz) {
nounsArr.push(nnz[i][Object.keys(nnz[i])[1]])
nnz[i][Object.keys(nnz[i])[1]] = nounsArr;
var Objlen = Object.keys(nnz[i]).length;
for (var j=0;j<Objlen;j++) {
var objKeys = Object.keys(nnz[i])[j];
newObj[objKeys] = nnz[i][objKeys];
}
}
nnz = newObj;
console.log(nnz);

Related

Trying to call a variable from JSON

New to AngularJS so apologies if my terminology isn't correct. I am trying to call a value that is in my JSON body, however the difference is that it's also inside another body called student.
{
"id": 3,
"teacherName": "N/A",
"students": [
{
"student": "n/a"
}
],
"status": "ALIVE"
}
My JS code consists of the following:
$scope.table = function () {
SpringDataRestService.get(
{
collection: "school",
resource: $scope.teacherSelected.id
},
function (response) {
var students= [];
for (var j = 0; j < response.students.length; j++) {
var entitlement= {
student: response[j].student,
};
students.push(entitlement);
}
$log.info(JSON.stringify(entitlement))
$scope.tableOptions = new NgTableParams({}, {
dataset: students,
counts: []
});
}
);
};
There is an error in for loop. Instead of:
student: response[j].student
you need to use this:
student: response.students[j].student
Check this working demo: DEMO

How to Filter Object Fields by a String Array

How can I filter an Object's field by an string array?
eg.
catValues:{
"1":{
value:10,
code:5
},
"3":{
value:10,
code:5
},
"5":{
value:10,
code:5
}
}
var chosenCats = ["1","5"]
result: {"1":{value:10, code:5}, "5":{value:10, code:5}}
You create a new object and insert just the chosen cat values.
var chosenCatValues = {};
for (var cat of chosenCats) {
chosenCatValues[cat] = catValues[cat];
}
Or you can use filter() and reduce():
var chosenCatValues = Object.keys(catValues)
.filter(key => chosenCats.includes(key))
.reduce((obj, key) => {
obj[key] = catValues[key];
return obj;
}, {});
Demo:
var catValues = {
"1": {
value: 10,
code: 5
},
"3": {
value: 10,
code: 5
},
"5": {
value: 10,
code: 5
}
};
var chosenCats = ["1", "5"];
var chosenCatValues = Object.keys(catValues)
.filter(key => chosenCats.includes(key))
.reduce((obj, key) => {
obj[key] = catValues[key];
return obj;
}, {});
console.log(chosenCatValues);
Try this:
Note: This will work with array of strings as well considering they are numbers.
var catValues = {
"1":{
value:10,
code:5
},
"3":{
value:10,
code:5
},
"5":{
value:10,
code:5
}
}
var chosen = ['1','5'];
const func = (chosen, catValues) => {
var ch = {};
chosen.map(chose => {
if(chose in catValues) {
ch[chose] = catValues[chose]
}
})
return ch
}
console.log(func(chosen, catValues))

using angular.forEach in filter

I have an array (1) with some id's and another array (2) with creatures, they have id (like in first array) and names. And I want to create new array (it will be looks like (1) id array, but only with id that in (2)). So I think that I need use filter.
(1)
$scope.main = ['dog', 'cat', 'bird', 'bug', 'human'];
(2)
$scope.creatures = [
{
id: 'cat',
name : 'fluffy'
},
{
id: 'cat',
name : 'mr.Kitty'
},
{
id: 'human',
name: 'Rachel'
},
{
id: 'cat',
name : 'Lucky'
},
{
id: 'cat',
name: 'Tom'
}
];
filter:
$scope.results = $scope.main.filter(function(item) {
angular.forEach($scope.creatures, function(creature) {
return item === creature.id;
});
});
I expect that it will be
$scope.results === ['cat', 'human'];
But I have
$scope.results // [0] empty array
Where I'm wrong? Plnkr example
It is not working because you are returning in the first iteration itself inside forEach loop. You can get it working as shown below :
Updated Plunker
$scope.results = [];
$scope.main.filter(function(item) {
angular.forEach($scope.creatures, function(creature) {
if(item === creature.id){
if( $scope.results.indexOf(item) === -1){
$scope.results.push(item);
}
}
});
});
Instead of looping again inside the filter, we can get the ids out of creatures array first and then filter them in main array like below :
$scope.results = [];
$scope.ids = $scope.creatures.map(function (creature){
return creature.id;
});
$scope.ids.map(function (id){
if($scope.main.indexOf(id) !== -1){
if( $scope.results.indexOf(id) === -1){
$scope.results.push(id);
}
}
});
console.log($scope.results);
Made few changes in your plunker, it is working now. Can you check with this code.
var app = angular.module('App', []);
app.controller('Ctrl', function($scope, $timeout){
$scope.main = ['dog', 'cat', 'bird', 'bug', 'human'];
$scope.creatures = [
{
id: 'cat',
name : 'fluffy'
},
{
id: 'cat',
name : 'mr.Kitty'
},
{
id: 'human',
name: 'Rachel'
},
{
id: 'cat',
name : 'Lucky'
},
{
id: 'cat',
name: 'Tom'
}
];
var array = [];
$scope.call = function() {
angular.forEach($scope.main,function(item){
angular.forEach($scope.creatures, function(creature) {
if(item == creature.id){
// console.log('item',item,' creatureId',creature.id);
if(array.indexOf(item) < 0 ){
array.push(item);
}
console.log(array);
}
});
$scope.results = array;
});
};
$scope.call();
console.log('result ',$scope.results);
});

Group by on a complex object in AngularJS

I've an array that contains assignments of employees on tasks, it looks like something like this:
$scope.assignments = [
{
employee: {
id:"1", firstname:"John", lastname:"Rambo"
},
task: {
name:"Kill everyone", project:"Destruction"
},
date: {
day:"01/01", year:"1985"
}
},
{
employee: {
id:"2", firstname:"Luke", lastname:"Skywalker"
},
task: {
name:"Find daddy", project:"Star Wars"
},
date: {
day:"65/45", year:"1000000"
}
},
{
employee: {
id:"1", firstname:"John", lastname:"Rambo"
},
task: {
name:"Save the world", project:"Destruction"
},
date: {
day:"02/01", year:"1985"
}
}
];
I would like to group by employee, for having something like this:
$scope.assignmentsByEmployee = [
{ //First item
id:"1",
firstname:"John",
lastname:"Rambo",
missions: [
{
name:"Kill everyone",
date:"01/01",
year:"1985"
},
{
name:"Save the world",
date:"02/01",
year:"1985"
}
]
},
{ //Second item
id="2",
firstname:"Luke",
lastname:"Skywalker",
missions: [
name:"Find daddy",
date:"65/45",
year:"1000000"
]
}
];
Is their a simple way to do this ? I tried something with a double forEach, but it leads me nowhere.
Hope I'm understandable :)
Thanks !
You should just be able to loop through the assignments array and create a 'keyed array' (which just means using an object in JavaScript) on employee ID. Then you just fill up the missions array as required.
Something like
// initialise a holding object
var assignmentsByEmployee = {};
// loop through all assignemnts
for(var i = 0; i < $scope.assignments.length; i++) {
// grab current assignment
var currentAssignment = $scope.assignments[i];
// grab current id
var currentId = currentAssignment.employee.id;
// check if we have seen this employee before
if(assignmentsByEmployee[currentId] === undefined) {
// we haven't, so add a new object to the array
assignmentsByEmployee[currentId] = {
id: currentId,
firstname: currentAssignment.employee.firstname,
lastname: currentAssignment.employee.lastname,
missions: []
};
}
// we know the employee exists at this point, so simply add the mission details
assignmentsByEmployee[currentId].missions.push({
name: currentAssignment.task.name,
date: currentAssignment.date.day,
year: currentAssignment.date.year
});
}
These leaves assignmentsByEmployee as an object, but you can simply foreach through it and convert it back to an array if required. E.g:
$scope.assignmentsByEmployee = [];
for(var employeeId in assignmentsByEmployee) {
$scope.assignmentsByEmployee.push(assignmentsByEmployee[employeeId]);
}

How do I get my Filters from Filtersfeature

I am using FiltersFeature:
this.features = {
ftype: 'filters',
encode: false,
local: true
};
I would like to access my current filters on my table. Ie. not the filter configuration object, but what the changes user has done to the table (I want to save this in the database).
There is a filters object on grid, but that just gives me the filter configuration from all the columns.
handler: function (btn) {
var grid = btn.up('grid');
grid.filters
}
I need the actual values. I'm looking for something like this:
var v = {
filter: {
column: 'name',
value: 'bob'
},
filter: {
column: 'date',
value1: '11.11.11',
value2: '12.12.12'
}
}
Anyone know where i can get this info?
The answer I found out was to use this method :)
myTableGrid.filters.getFilterData()
I get something like this :
v = [{
"field": "myColumn1",
"data": {
"type": "string",
"value": "anna"}
}, {
"field": "myColumn2_fixedvalue",
"data": {
"type": "list",
"value": [60]}
}]
Filter does not contain any values.
You should parse actual values from the grid.
var columnTitle = [];
var fieldName = [];
var data = [];
var visibleColumns = grid.query('gridcolumn:not([hidden])');
visibleColumns.forEach(function(c) {
columnTitle.push(c.text);
fieldName.push(c.dataIndex);
});
for (rowIndex = 0; rowIndex < grid.store.getCount(); rowIndex++) {
var row = grid.getView().getRow(rowIndex);
var fieldValues = Ext.fly(row).query('div.x-grid-cell-inner');
var map = {}
for (colIndex = 0; colIndex < fieldName.length; colIndex++) {
map[fieldName[colIndex]] = fieldValues[colIndex].textContent;
}
data.push(map);
}
As a result, you will get an array of objects, something like
[{"user.login":"iivanov","email":"ivanov#mail.com"},{"user.login":"ppetrov","email":"petrov#mail.com"},{"user.login":"plosev","email":"elk#gmail.com"}]

Resources