I have this array :
var hemicycle = {
Group1 : [{
GroupName : "Les bests",
Member1 : [{
Name : "Loris Plasson",
Seat : 4,
Vignette : "PhotoURL"
}],
Member2 : [{
Name : "Anne-Sophie",
Seat : 3,
Vignette : "PhotoURL"
}]
}]
I want to push the object Member1 or Member2 on another object depending of the Seat value.
To do that I think I need to "search" for the Seat value with a for loop and retrieve the object, but all the examples I found on StackOverflow were with simple arrays like this :
var array = [
{ name:"string 1", value:"this", other: "that" },
{ name:"string 2", value:"this", other: "that" }
];
With those simple arrays they are able to use something like a for loop with array[i].
But in my case I really don't know what to do...
UPDATE : What I want : The Member object which include the corresponding Seat value searched. Then I push the Member object to another object.
Thanks for any help.
The data structure that you use doesn't reflect what you are trying to convey, and in addition is very heard to traverse.
I suggest creating an array of groups. Each group is an object, that has the members property, which is an array of member objects:
[{
"GroupName": "Les bests",
"members": [{
"Name": "Loris Plasson",
"Seat": 4,
"Vignette": "PhotoURL"
},
{
"Name": "Anne-Sophie",
"Seat": 3,
"Vignette": "PhotoURL"
}
]
}]
Using this structure, you find a member using 2 for loops - one to iterate the groups, and the other to iterate the members of each group. Once a member is found, the function returns the member's object immediately. If not undefined is returned:
var groups = [{"GroupName":"Les bests","members":[{"Name":"Loris Plasson","Seat":4,"Vignette":"PhotoURL"},{"Name":"Anne-Sophie","Seat":3,"Vignette":"PhotoURL"}]}];
var seatNum = 4;
function findMember(seatNum) {
var members;
for(var i = 0; i < groups.length; i++) {
members = groups[i].members;
for(var j = 0; j < members.length; j++) {
if(members[j].Seat = seatNum) {
return members[j];
}
}
}
}
var member = findMember(seatNum);
console.log(member);
Related
I need to get a list of all the key names in the following JSON object:
var myJSON = [
{
"Employees_Name": "Bill Sanders",
"Work_plan_during_my_absence": "Work from home",
"Assigned To-Manager Approval": [
"mymanager#gmail.com"
],
"AbsenceVacation_Summary": [
{
"Computed_Leave_Days": 2,
"From_Date": "2018-08-20",
"To_Date": "2018-08-21",
"Id": "Shccbcc230_a30f_11e8_9afa_25436d674c51"
}
],
"Leave_Type": "Work from Home",
"Reporting_Manager": "My Manager",
"Total_Days": 2,
}
]
When I use the Object.keys method, it retrieves only the top level key names:
var keys_arr = Object.keys(myJSON[0]);
console.log(keys_arr);
The result is an array:
"[ 'Employees_Name', 'Work_plan_during_my_absence', 'Assigned To-Manager
Approval', 'AbsenceVacation_Summary', 'Leave_Type', 'Reporting_Manager',
'Total_Days']"
The key names that are missing are the ones inside of 'AbsenceVacation_Summary'.
I think what I need to do is loop through the array of names returned and see if the value is an object or an array...but I don't know how to do this. Please advise.
You're right you need to walk your object structure recursively to discover nested objects and collects their keys:
function collectKeys(inputObject, outputKeys) {
if (Array.isArray(inputObject)) {
for(let i = 0; i < inputObject.length; i++) {
collectKeys(inputObject[i], outputKeys);
}
} else if (typeof inputObject === 'object') {
Object.keys(inputObject).forEach(function(key) {
outputKeys.push(key);
collectKeys(outputKeys[key], outputKeys);
});
}
}
var collectedKeys = [];
collectKeys(myJSON, collectedKeys);
Working fiddle here
Result will show in console
References
javascript typeof
javascript Array.isArray
javascript Array.forEach
I have two arrays
$scope.tags = [{ "id": 1, "name": "python" }, { "id": 2, "name": "NodeJs" }, { "id": 3, "name": "git" }]
Other one is
$scope.skillsInterested = [1,2];
What is want to do ?
How can i map the above arrays and print only names of the id's in$scope.skillsInterested
I want to print names in first array only the id's present in second.
I have tried this after getting several answers
var tag_map = {};
for (var x = 0; x < $scope.tags.length; x++) {
tag_map[$scope.tags[x]['id']] = $scope.tags[x]['name'];
}
$scope.skillsInts = $scope.skillsInterested.map(function(x) {
return tag_map[x]
On running console.log
console.log("Result", tag_map);
It sometimes give result sometimes it gives 'map' of undefined.
TypeError: Cannot read property 'map' of undefined
at controllers.js:141
at angular.js:16383
at m.$eval (angular.js:17682)
at m.$digest (angular.js:17495)
at m.$apply (angular.js:17790)
at l (angular.js:11831)
at J (angular.js:12033)
at XMLHttpRequest.t.onload (angular.js:11966)
Thanks in advance.
Make a map of your data that looks like this:
var tagMap = { 1: "python", 2: "NodeJs" /* etc. */ };
You can do this by looping over your tags and adding a new property to an object. reduce lets you do this without creating any extra variables.
Then, you can select names from your newly created object using the [] notation: tagMap[1] returns "pyhton".
var tags = [{ "id": 1, "name": "python" }, { "id": 2, "name": "NodeJs" }, { "id": 3, "name": "git" }]
var selectedExpTags = [1,2];
// Make a map for `id: name`
var tagMap = tags.reduce(function(map, tag) {
map[tag.id] = tag.name;
return map;
}, {});
// Quickly select names from the map:
var selectedNames = selectedExpTags.map(function(id) {
return tagMap[id];
});
console.log(selectedNames);
Using this approach, you minimise the iterations over your data. The creation of the map loops over the tags once. Creating the array with names, loops over the selected tags once. So, roughly, the "loop count" is tags.length + selectedTags.length. If you would use an indexOf based approach, your loop count would be tags.length * selectedTags.length.
Use the filter function for first, and then check the id's existnent then map the names from the array.
var first = [{ "id": 1, "name": "python" }, { "id": 2, "name": "NodeJs" }, { "id": 3, "name": "git" }];
var selectedExpTags = [1,2];
var names = first.filter(item => selectedExpTags.some(id => item.id === id)).map(item => item.name);
console.log(names);
You can loop over $scope.selectedExpTags and get a list of all names. You can use array.find if you want first value only.
Sample
var first = [
{ "id": 1, "name": "python" },
{ "id": 2, "name": "NodeJs" },
{ "id": 3, "name": "git" }];
var selectedExpTags = [1,2];
var names = selectedExpTags.map(x=> first.find( y=> y.id === x ).name )
console.log(names);
$scope.newArray = []; // If you need a new array to work with
angular.forEach($scope.tags, function(tag){
$scope.selectedExpTags.forEach(function(selectedTag){
if(selectedTag == tag.id){
//tag.hide = false; // - If you want to update the current array
$scope.newArray.push(tag);
}
// else{ // - If you want to update the current array
// tag.hide = true;
// }
})
})
Lodash is more efficient than angular for manipulating data.
I am having the below JSON object.
"Department": [
{
"depType": "Testing",
"name": "xyz",
"address":""
},
{
"deptype": "Developer",
"name": "abc"
}
]
I want to create another object based on the type of deptartment (depType). Something like this
"Testing":{
"name": "xyz",
"address":""
},
"Developer":{
"name": "abc"
}
With the help of Object.keys, I was able to get the keys
You had some Property-naming issues with camelCased "depType". Fix that.
Create a new copy of the desired object to manipulate using JSON.parse(JSON.stringify(orgObj))
Loop that object to find the desired Property "Department"
Since Department is an Array of Objects you need to loop that Array for(var i=0; i<dep.length; i++).
Than you'll need to match if that Array contains arrObj.hasOwnProperty( "depType" )
if successful you can than fill your new object with all the info newObj[arrObj.depType] = arrObj;
Since now, inside your new object there's also the good old "depType" property you can get rid of it using delete.
jsBin demo
var myjson = {
"Department": [
{
"depType": "Testing", // NOTE: "camelCase"
"name": "xyz",
"address":""
},
{
"depType": "Developer", // FIX: "camelCase" !!
"name": "abc"
}
]
};
function depTypify( orgObj ) {
var objCopy = JSON.parse(JSON.stringify(orgObj)); // Fresh copy
var newObj = {};
for(var prop in objCopy){
if(prop === "Department") {
var dep = objCopy[prop]; // get Department Array
for(var i=0; i<dep.length; i++) { // Loop array
var arrObj = dep[i]; // Explore Each Array Object
if(arrObj.hasOwnProperty( "depType" )) {
newObj[arrObj.depType] = arrObj;
delete arrObj.depType; // We don't need it any more
}
}
}
}
return newObj;
}
var myNewJson = depTypify( myjson );
if you do than console.log( myNewJson ) this is what you'll get:
[object Object] {
Developer: [object Object] {
name: "abc"
},
Testing: [object Object] {
address: "",
name: "xyz"
}
}
The nice thing is that your old json is still intact.
Below is my json structure. On success of collection.fetch() i'm looping through the structure.
Currently i use
this.collection.each(function(model) { .. }
How do i obtain key name like plants, animals and instead loop using the names.
JSON
var jsonObj = { // 0 - recommended , 1 - New
"plants" : [
{
"title" : "title1",
"desc": "description.."
},
{
"title" : "titl2",
"desc": "description."
}
],
"animals" : [
{
"title" : "title1",
"desc": "description.."
},
{
"title" : "titl2",
"desc": "description."
}
]
};
Snapshot of collection
This would work, but you'd use a normal for loop, not "each":
for(i in jsonObj){
alert(i);
}
here is a fjsfiddle: http://jsfiddle.net/r5nwP/
Is that what you're after?
You can use the underscore keys to get a list of names:
var thenames =_.keys(yourobject);
In this case thenames will contain a list of the keys you are looking for. Here is the documentation for it:
http://underscorejs.org/#keys
keys_.keys(object)
Retrieve all the names of the object's properties.
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
If I have array of objects like this
[
{
"name" : "some name",
"more data" : "data",
...
},
{
"name" : "another name",
"more data" : "data",
...
},
...
]
And I want to copy the array, but only the name element in the object so that I have this:
[
{
"name" : "some name",
},
{
"name" : "another name",
},
...
]
Is there a short hand way to do this without writing a loop?
No, you have to do this with a loop, but in can still be short:
for(var i = 0; i < arr.length; i++)
arr[i] = {name: arr[i].name};
If you use any sort of framework or library all it will do is hide the loop from you. It will still loop through everything.
Example
No, there is no way of doing this without a loop. Can I suggest you do this with a bit of prototyping magic. (Note, this can be done with some map or forEach magic which just hides away the fact that you're looping. I'll leave this with the loop to illustrate the idea)
Array.prototype.clone = function(predicate)
{
var newArray = [];
for(var i = 0;i <this.length; i++){
var newElement = {};
for(x in this[i]){
if(predicate(x)){
newElement[x] = this[i][x];
}
}
newArray.push(newElement);
}
return newArray;
}
This allows you to clone an array, passing in a function that decides which property to keep from each element in the array. So given an array like:
var arr = [
{
"name" : "some name",
"more data" : "data"
},
{
"name" : "another name",
"more data" : "data"
}
];
You can do
var newArray = arr.clone(function(x){ return x == "name";});
Which will return you an array with the same number of objects, but each object will just have the name element.
Live example: http://jsfiddle.net/8BGmG/