My object:
"hockey": {
stats: {
skaters: {
regular: [
{name: "stat1", key: "statkey1"}
{name: "stat2", key: "statkey2"}
{name: "stat3", key: "statkey3"}
]
},
goalies: {
regular: [
{name: "stat1", key: "statkey4"}
{name: "stat2", key: "statkey5"}
{name: "stat3", key: "statkey6"}
]
}
}
}
My code:
var stats = [];
var key = "";
for (position in sport.stats) {
for (stat_group in position) {
for (stat in stat_group) {
key = stat.key;
stats[key] = true;
}
}
}
I'm trying to use the above code to grab the property key from each object located within sport.stats.position.stat_group. Each sport has a different number of positions and stat groups, hence the triple for loop. I'm not getting any console errors it just isn't grabbing the key at all and the iterator variables aren't evaluating to objects but integers.
Here's what I want the resulting stats object to be:
{
"statkey1": true,
"statkey2": true,
"statkey3": true,
...
}
Hope you guys can help! Thanks!
The JS for...in loop iterates through the keys, not values. If you want to iterate an object fully, you can do so like this:
for (key in sports.stats) {
var position = sports.stats[key];
for (group_key in position) {
var stat_group = position[group_key];
for (stat_key in stat_group) {
stat_group[stat_key] = true;
}
}
}
For...in in javascript gives you the key of the object, not the value.
According to your logic, this is what you meant to do:
var stats = {};
var key = "";
for (position in sport.stats) {
for (stat_group in sport.stats[position]) {
for (stat in sport.stats[position][stat_group]) {
key = sport.stats[position][stat_group][stat].key;
stats[key] = true;
}
}
}
Related
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
var has = {
name: 'dog',
surname: 'cat',
skills : {
football: true,
basketball: true,
volleyball: true
}
}
var pas = {
name: 'dolphin',
surname: 'cat',
skills : {
football: false,
basketball: false,
volleyball: true
}
}
function compare(Obj1, Obj2) {
var values1 = Object.values(Obj1);
var values2 = Object.values(Obj2);
var equivalent = [];
for (var i = 0; i < values1.length; i++) {
for (var j = 0; j < values2.length; j++) {
if (i === j ) {
equivalent.push(values1[i]);
}
}
}
console.log(equivalent, values1, values2);
}
compare(has, pas);
I am trying to compare 2 objects by their values using nested for loops. It might not be the best method to use for such a simple comparison but as a new starter, I really would like to know why it's not working properly.
There are some mistakes in your code. First of all, you are comparing i with j, when you actually want to compare some values.
I'd solve the problem by taking the keys of the object and iterating among them. If both the objects have those keys AND the values are the same, I'll add them to the equivalent array.
var has = {
name: 'dog',
surname: 'cat',
skills: {
football: true,
}
}
var pas = {
name: 'dolphin',
surname: 'cat',
skills: {
football: true,
}
}
function compare(Obj1, Obj2) {
var values1 = Object.values(Obj1);
var values2 = Object.values(Obj2);
var equivalent = [];
var keys = Object.keys(Obj1);
keys.forEach(k => {
if (Obj1.hasOwnProperty(k) && Obj2.hasOwnProperty(k)) {
if (Obj1[k] === Obj2[k]) {
equivalent.push(Obj1[k]);
}
}
});
console.log(equivalent);
}
compare(has, pas);
However, this won't work for nested objects, as in your case. Why? Because even if the nested objects (skills in your case) have the same values, they are different objects, different references, so the comparison will fail. See how objects comparison in js works here or here.
In this case, a general recursive solution may work like the one below:
var has = {
name: 'dog',
surname: 'cat',
skills: {
football: true,
basketball: true,
volleyball: true
}
}
var pas = {
name: 'dolphin',
surname: 'cat',
skills: {
football: true,
basketball: false,
volleyball: false
}
}
function compare(Obj1, Obj2) {
var values1 = Object.values(Obj1);
var values2 = Object.values(Obj2);
var equivalent = [];
var keys = Object.keys(Obj1);
keys.forEach(k => {
if (Obj1.hasOwnProperty(k) && Obj2.hasOwnProperty(k)) {
if (typeof Obj1[k] === 'object') {
let recursiveAnswer = compare(Obj1[k], Obj2[k]);
equivalent.push(...recursiveAnswer);
} else if (Obj1[k] === Obj2[k]) {
equivalent.push(Obj1[k]);
}
}
});
return equivalent;
}
let equiv = compare(has, pas);
console.log(equiv);
Here, if I encounter a value that is also an object, I call the function again. The partial answer will be pushed once the recursive call is done. You'll see that the final answer will also contain the true value here, value that is from the football field, since they are equal (in my example). Having true/false values in the array among the cat string may be confusing, so you can actually add the key name instead of the value for the bool fields.
You could modify the if and the push like this:
if (typeof Obj1[k] === 'boolean') {
equivalent.push(`(${k}, ${Obj1[k]})`);
} else {
equivalent.push(Obj1[k]);
}
This will produce the following output:
[
"cat",
"(football, true)"
]
Let me know if you have any questions.
Cheers!
I have the following object being returned. I am counting a list of names by reading from a json file and storing the results in a new object.
{
ted: 501,
jeff: 40,
tony: 90
}
The following function creates an object with the names as properties and the count as their values.
function countNames(json){
var count = {};
for (var i = 0, j = json.length; i < j; i++) {
if (count[json[i].name]) {
count[json[i].name]++;
}
else {
count[json[i].name] = 1;
}
}
return count;
}
I need to create an array of objects that generate a result like this.
[
{
name: 'ted',
total: 501
},
{
name: 'jeff',
total: 40
}
{
name: 'tony',
total: 90
}
]
I am not sure what the best approach and most efficient way of achieving this is. Any help is appreciated.
Consider this following Javascript snippet:
for (var item in obj) {
result.push({
name: item,
total: obj[item]
});
}
Working DEMO
Output:
[
{
"name":"ted",
"total":501
},
{
"name":"jeff",
"total":40
},
{
"name":"tony",
"total":90
}
]
I don't understand how your code example relates to the question, but this turns the data in the first format into the last format:
var output = Object.keys(input).map(function(key) {
return {
name: key,
count: input[key]
}
});
it uses functional programming style, which usually leads to cleaner code.
JSBin
I am trying to get the parent of a specific (referenced) object in an array.
Example:
var data = [
{
key: "value1"
children: [
{
key: "value2"
},
{
key: "value3"
children: [
{
key: "value3a"
},
{
key: "value3b"
}
]
}
]
},
{
key: "value4"
}
];
When some stuff happens, I get the following:
var clicked = {
key: "value3a"
}
In this case I know that value3a has been clicked, and it's databound with the data variable.
The question is, how do I easily get the parent of clicked? It should return the whole children-array of value3 which I want:
[
{
key: "value3a"
},
{
key: "value3b"
}
]
Note: currently I am using UnderscoreJS to find the object of my array. So maybe UnderscoreJS could help?
Just create a child-parent map so that you can look up what you need:
var map = {};
function recurse(arr, parent) {
if (!arr) return;
for (var i=0; i<arr.length; i++) { // use underscore here if you find it simpler
map[arr[i].key] = parent;
recurse(arr[i].children, arr[i]);
}
}
recurse(data, {key:"root", children:data});
Now, in your event handler you can trivially use that map to look up your siblings:
map[clicked.key].children
You could use a recursive reduce function.
// Given
var data = [
{
key: "value1",
children: [
{
key: "value2"
},
{
key: "value3",
children: [
{
key: "value3a"
},
{
key: "value3b"
}
]
}
]
},
{
key: "value4"
}
];
var clicked = {
key: "value3a"
};
We can define a recursive reduce function, and give it the parent
as the context.
var rec_reduce = function(memo, obj) {
if(obj.key == clicked.key) {
return this || memo;
}
return _.reduce(obj.children, rec_reduce, memo, obj.children) || memo;
};
// Now we can lookup the key in clicked with one line
_.reduce(data, rec_reduce, null, data);
// Returns [{key: "value3a"}, {key: "value3b"}]
Or, if you want to leverage underscore to make a map as suggested in the first answer, that is even simpler:
var map = {};
var rec_map = function(obj, i, parent) {
map[obj.key] = parent;
_.each(obj.children, rec_map);
};
_.each(data, rec_map);
// Now getting the parent list is just a look up in the map
map[clicked.key]
// Returns [{key: "value3a"}, {key: "value3b"}]
My problem is to merge an object and an array of objects.
Here's my object:
{
model1: ["model1-coupe", "model1-hatchback", "model1-cabriolet"],
model2: ["model2-coupe","model12-hatchback","model2-cabriolet"],
model3: ["model3-coupe","model4-hatchback","model4-cabriolet"]
}
Here's my array of objects:
[
{image: "/path/to/image/model1.jpg"},
{image: "/path/to/image/model2.jpg"},
{image: "/path/to/image/model3.jpg"}
]
I'd like to merged them like that:
[
{
image: "/path/to/image/model1.jpg",
model1: ["model1-coupe", "model1-hatchback", "model1-cabriolet"]
},
{
image: "/path/to/image/model2.jpg",
model2: ["model2-coupe", "model2-hatchback", "model2-cabriolet"]
},
{
image: "/path/to/image/model3.jpg",
model3: ["model3-coupe", "model3-hatchback", "model3-cabriolet"]
}
]
How do I do that? I can use either JavaScript or Underscore.
Thanks in advance
EDIT: see how the merging result would actually be:
[
{
image: "/path/to/image/model1.jpg",
cars: ["model1-coupe", "model1-hatchback", "model1-cabriolet"]
},
{
image: "/path/to/image/model2.jpg",
cars: ["model2-coupe", "model2-hatchback", "model2-cabriolet"]
},
{
image: "/path/to/image/model3.jpg",
cars: ["model3-coupe", "model3-hatchback", "model3-cabriolet"]
}
]
for (var i = 0, key; i < modelArray.length; i++) {
modelArray[i].cars = modelObject[Object.keys(modelObject)[i]];
}
This will loop the array and add the property to the object. This assumes that the object properties are all in the proper order.
In each iteration, it loops up which property it's up to using Object.keys(). Then, it sets that key of the object in the array to that property of the model object.
You can do something like
var models = {
model1: ["model1-coupe", "model1-hatchback", "model1-cabriolet"],
model2: ["model2-coupe", "model12-hatchback", "model2-cabriolet"],
model3: ["model3-coupe", "model4-hatchback", "model4-cabriolet"]
}
var images = [{
image: "/path/to/image/model1.jpg"
}, {
image: "/path/to/image/model2.jpg"
}, {
image: "/path/to/image/model3.jpg"
}]
for (var key in models) {
if (models.hasOwnProperty(key)) {
var idx = +key.match(/\d+$/)[0] - 1;
images[idx][key] = models[key]
}
}
console.log(images)
try something like this:
var result = [];
var models = {
// your models object
}
var images = [
// your images array
];
for(var i=0, key in models) {
var model = models[key];
var image = images[i++];
result.push( { image: image, model: model } );
}