Here is my code
var dataGroupByParentCategory = function(data){
return _.groupBy(data, function(entry){
return entry.category.parent;
});
};
var parentCategorySum = function(data) {
var result = {};
_.forEach(_.keys(this.dataGroupByParentCategory(data)), function(parentCategory){
var that = this;
console.log(parentCategory);
var s = _.reduce(that.dataGroupByParentCategory[parentCategory], function(s, entry){
console.log('>' + entry); // Can not see entry here
return s + parseFloat(entry.amount);
}, 0);
result[parentCategory] = s;
});
return result;
};
and data looks like
'data': [
{
'category': {
'uri': '/categories/0b092e7c-4d2c-4eba-8c4e-80937c9e483d',
'parent': 'Food',
'name': 'Costco'
},
'amount': '15.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Food',
'name': 'India Bazaar'
},
'amount': '10.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Food',
'name': 'Sprouts'
},
'amount': '11.1',
'debit': true
}, ...
Problem?
I can not see value of entry as seen in code above
console.log('>' + entry); // Can not see entry here
I am learning JavaScript and not very well versed with concept of scopes, is that is causing issue here?
It seems your dataGroupByParentCategory function is global, so you don't need use this or that to access it. Also it seems you make a typo in dataGroupByParentCategory[parentCategory]. It must be dataGroupByParentCategory(parentCategory)
After spending sometime with code, I realized I was doing it incorrectly, the actual code now is
var parentCategorySum = function(data) {
var result = {};
var dataGroupByParent = dataGroupByParentCategory(data);
_.forEach(_.keys(dataGroupByParent), function(parentCategory){
var s = _.reduce(dataGroupByParent[parentCategory], function(s, entry){
return s + parseFloat(entry.amount);
}, 0);
result[parentCategory] = s;
});
return result;
};
Related
I'm trying to do this:
var array = [];
array[1] = {
'name': 'Raul'
};
array[5] = {
'name': 'Ilidio'
};
array[20] = {
'name': 'Ferreira'
};
array[1001] = {
'name': 'Reis'
};
console.log(array);
When I run console.log() this appears:
I want only the keys that I defined to appear. Am I doing something wrong to give me all the keys up to 1001?
That is what an array is - it sounds like you want an object:
var obj = {};
obj[1] = {
'name': 'Raul'
};
obj[5] = {
'name': 'Ilidio'
};
obj[20] = {
'name': 'Ferreira'
};
obj[1001] = {
'name': 'Reis'
};
console.log(obj);
I am writing a memory card game. Each time when I refresh the page, the cards are supposed to place in a random position but it turns out that they remain in the same position.
here is the code :
var cardsArray = [{
'name': 'ball',
'img': '../img/ball.png',
},
{
'name': 'building',
'img': '../img/building.png',
},
{
'name': 'fan',
'img': '../img/fan.png',
},
{
'name': 'fish',
'img': '../img/fish.png',
},
{
'name': 'fishball',
'img': '../img/fishball.png',
},
{
'name': 'flower',
'img': '../img/flower.png',
},
{
'name': 'hill',
'img': '../img/hill.png',
},
{
'name': 'orange',
'img': '../img/orange.png',
},
{
'name': 'boo',
'img': '../img/boo.png',
},
{
'name': 'shoe',
'img': '../img/shoe.png',
},
];
var firstGuess = '';
var secondGuess = '';
var count = 0;
var previousTarget = null;
var delay = 1200;
var moves;
var matched;
var score;
var game = document.getElementById('game');
var grid = document.createElement('section');
const gameGrid = cardsArray
.concat(cardsArray)
.sort(function() {
0.5 - Math.random()
});
function startGame() {
grid.setAttribute('class', 'grid');
game.appendChild(grid);
moves = 0;
score = 0;
matched = 0;
document.getElementById("moves").innerHTML = moves;
document.getElementById("score").innerHTML = score;
gameGrid.forEach(function(item) {
const {
name,
img
} = item;
const card = document.createElement('div');
card.classList.add('card');
card.dataset.name = name;
const front = document.createElement('div');
front.classList.add('front');
const back = document.createElement('div');
back.classList.add('back');
back.style.backgroundImage = `url(${img})`;
grid.appendChild(card);
card.appendChild(front);
card.appendChild(back);
});
}
Sorry, I know it might be a bit long, but I guess the problem might be here:
const gameGrid = cardsArray
.concat(cardsArray)
.sort(function() {
0.5 - Math.random()
});
Did I do something wrong here? How can i fix it?
You're not actually returning the random value to sort on.
const gameGrid = cardsArray
.concat(cardsArray)
.sort(function() {
return 0.5 - Math.random()
});
I have this array and variable:
var freqId = 45;
$scope.frequencies = [{Id:124,name:'qqq'},
{Id:589,name:'www'},
{Id:45,name:'eee'},
{Id:567,name:'rrr'}]
I use this row to get all id's from array above:
var inspectionsId = $scope.frequencies.map(function (obj) { return obj.Id; })
The result I get is:
var Id's = [124,589,45,567];
I need to change this row:
$scope.frequencies.map(function (obj) { return obj.Id; })
to retrive all id from frequencies array except where Id equal to freqId variable.
For example desired result is:
var inspectionsId = [124,589,567];
Any idea how can I implemet it?
You can also use Array.prototype.reduce to do both filtering and mapping in a single loop:
var freqId = 45;
$scope = {}; // Dummy scope
$scope.frequencies = [{
Id: 124,
name: 'qqq'
}, {
Id: 589,
name: 'www'
}, {
Id: 45,
name: 'eee'
}, {
Id: 567,
name: 'rrr'
}]
var result = $scope.frequencies.reduce(function(result, current) {
if (current.Id != freqId) {
result.push(current.Id);
}
return result;
}, []);
console.log(JSON.stringify(result));
map is designed to transform data, not filter it. Chain it with filter for the latter.
var freqId = 45;
var input = [{
Id: 124,
name: 'qqq'
}, {
Id: 589,
name: 'www'
}, {
Id: 45,
name: 'eee'
}, {
Id: 567,
name: 'rrr'
}];
var output = input.map(function(obj) {
return obj.Id;
}).filter(function(element) {
return element != freqId
});
console.log(output);
You can use Array.prototype.filter:
var inspectionsId = $scope.frequencies
.map(function(obj) { return obj.Id; })
.filter(function(id) { return id !== 45 })
You'll have seen the filter answers. 99.999% of the time, that's the way to go.
If you have a truly massive array and you think it's important to make just a single pass through it, you could give yourself a function combining map and filter:
// A value to use to mean "leave entry out"
Object.defineProperty(Array.prototype, "OMIT", {
value: {}
});
// The utility function
Object.defineProperty(Array.prototype, "mapFilter", {
value: function(f, thisArg, omissionFlag) {
var result = [];
if (arguments.length < 3) {
omissionFlag = Array.OMIT;
}
Object.keys(this).forEach(function(index) {
var value = f.call(thisArg, this[index], index, this);
if (value !== omissionFlag) {
result.push(value);
}
}, this);
return result;
}
});
// Using it
var freqId = 45;
var input = [{Id: 124, name: 'qqq'}, {Id: 589, name: 'www'}, {Id: 45, name: 'eee'}, {Id: 567, name: 'rrr'}];
var output = input.mapFilter(function(obj) {
return obj.Id == freqId ? Array.OMIT : obj.Id;
});
console.log(output);
This version accepts up to three arguments:
The map/filter function
The value to use as this during callbacks
The value to use to mean "omit this entry," which defaults to Array.OMIT
It calls its callback with the value, index, and array just like forEach and map and such do.
Again, though, I'll emphasize that in the vast, vast majority of cases, filter and then map (or map and then filter if the map makes filtering easier) is the way to go.
That said, a generic "loop with memo" function has broader applicability:
// The utility function
Object.defineProperty(Array.prototype, "memoLoop", {
value: function(memo, f, thisArg) {
Object.keys(this).forEach(function(index) {
f.call(thisArg, memo, this[index], index, this);
}, this);
return memo;
}
});
// Using it
var freqId = 45;
var input = [{Id: 124, name: 'qqq'}, {Id: 589, name: 'www'}, {Id: 45, name: 'eee'}, {Id: 567, name: 'rrr'}];
var output = input.memoLoop([], function(result, obj) {
var id = obj.Id;
if (id != freqId) {
result.push(id);
}
});
console.log(output);
It's a bit like Array#reduce but assumes an unchanging memo value (in our case, the new array), which simplifies the callback somewhat.
So, I have this function that works to get a JSON object but I want to make it simplier so I created a function to get the values of the JSON object. Why doesn't it work?
var itemData = {
weapon: function () {
return {
1: {
'name': 'Dagger',
'extra_skill': 'none',
'cost': 500,
'attack': 5
},
2: {
'name': 'Pickaxe',
'extra_skill': 'mining',
'cost': 25,
'attack': 5
}
}
},
getWeapon: function (value, x) {
var obj = JSON.parse(value);
return itemData.weapon()[x].obj
}
}
// outputs: Dagger
console.log(itemData.weapon()[1].name)
// Get the name of weapon 1
// however, it outputs: Uncaught SyntaxError: Unexpected token a
console.log('Getting weapon... ' + itemData.getWeapon('name', 1))
What am I doing wrong?
You actually don't need JSON parsing at all to get this working, because there is nowhere where you have a JSON string that needs to be parsed.
Here is a working example:
var itemData = {
weapon: function () {
return [
{
'name': 'Dagger',
'extra_skill': 'none',
'cost': 500,
'attack': 5
},
{
'name': 'Pickaxe',
'extra_skill': 'mining',
'cost': 25,
'attack': 5
}
];
},
getWeapon: function (value, x) {
return itemData.weapon()[x][value];
}
}
// outputs: Dagger
console.log(itemData.weapon()[0].name)
// outputs: Getting weapon... Pickaxe
console.log('Getting weapon... ' + itemData.getWeapon('name', 1))
Below is the JSON data.
JSON :
[{
"Code":"US-AL",
"Name":"Alabama",
"Population":4833722
},
{
"Code":"US-AK",
"Name":"Alaska",
"Population":735132
},
{
"Code":"US-AZ",
"Name":"Arizona",
"Population":6626624
},
{
"Code":"US-AR",
"Name":"Arkansas",
"Population":2959373
},
{
"Code":"US-CA",
"Name":"California",
"Population":38332521
},
{
"Code":"US-CO",
"Name":"Colorado",
"Population":5268367
},
{
"Code":"US-CT",
"Name":"Connecticut",
"Population":3596080
}]
I wanted to convert that data to this format.
[{
"US-AL": {
"name" : "Alabama",
"population" : 4833772
},
"US-AK": {
"name" : "Alaska",
"population" : 735132
}
}]
I tried with this function and separated the name and population from it.
var ParentData = [];
var ChildData = {"name": [], "population": []};
data.forEach(function(val, i) {
ParentData.push(val.Code);
ChildData.name.push(val.Name);
ChildData.population.push(val.Population);
})
But I'm not that expert in this. Just a learner and I don't know how to push to the parent data which gets aligned to it respectively.
Any help will be very much helpful for me to achieve this.
Thanks in advance.
Try this:
var newData = {};
data.forEach(function(val) {
newData[val.Code] = {name: val.Name, population: val.Population};
});
Keep in mind that forEach isn't natively supported by IE8-, although it can be polyfilled. This works in every browser:
for (var i = 0; i < data.length; i++)
newData[data[i].Code] = {name: data[i].Name, population: data[i].Population};
Or, since you added the "jquery" tag, you can also use:
$.each(data, function() {
newData[this.Code] = {name: this.Name, population: this.Population};
});
Try with native map of javascript
var newData = data.map(function (obj) {
var newObj = {};
newObj[obj.Code] = {};
newObj[obj.Code].name = obj.Name;
newObj[obj.Code].population = obj.Population;
return newObj;
});
console.log(newData)
[{
"US-AL":{
"name":"Alabama",
"population":4833722
}
},
{
"US-AK":{
"name":"Alaska",
"population":735132
}
},
{
"US-AZ":{
"name":"Arizona",
"population":6626624
}
},
{
"US-AR":{
"name":"Arkansas",
"population":2959373
}
},
{
"US-CA":{
"name":"California",
"population":38332521
}
},
{
"US-CO":{
"name":"Colorado",
"population":5268367
}
},
{
"US-CT":{
"name":"Connecticut",
"population":3596080
}
}
]
And the code:
var newDatas = datas.map(function(item) {
var obj = {};
obj[item.Code] = { name: item.Name, population: item.Population };
return obj;
});
datas is the array containing your original source.