Related
I've taken the following sample from a different question. And I am able to identify the object. But I also need to find our the position of that object. For example:
var arr = [{
Id: 1,
Categories: [{
Id: 1
},
{
Id: 2
},
]
},
{
Id: 2,
Categories: [{
Id: 100
},
{
Id: 200
},
]
}
]
If I want to find the object by the Id of the Categories, I can use the following:
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
However, I also need to know the position of the object in the array. For example, if we are looking for object with Id = 100, then the above code will find the object, but how do I find that it's the second object in the main array, and the first object in the Categories array?
Thanks!
Well, if every object is unique (only in one of the categories), you can simply iterate over everything.
var arr = [{
Id: 1,
Categories: [{Id: 1},{Id: 2}]
},
{
Id: 2,
Categories: [{Id: 100},{Id: 200}]
}
];
var needle = 100;
var i = 0;
var j = 0;
arr.forEach(function(c) {
c.Categories.forEach(function(e) {
if(e.Id === needle) {
console.log("Entry is in position " + i + " of the categories and in position " + j + " in its category.");
}
j++;
});
j = 0;
i++;
});
function findInArray(needle /*object*/, haystack /*array of object*/){
let out = [];
for(let i = 0; i < haystack.lenght; i++) {
if(haystack[i].property == needle.property) {
out = {pos: i, obj: haystack[i]};
}
}
return out;
}
if you need the position and have to filter over an property of the object you can use a simple for loop. in this sample your result is an array of new object because there can be more mathches than 1 on the value of the property.
i hope it helps
Iterate over the array and set index in object where match found
var categoryGroups = [{
Id : 1,
Categories : [{
Id : 1
}, {
Id : 2
},
]
}, {
Id : 2,
Categories : [{
Id : 100
}, {
Id : 200
},
]
}
]
var filterVal = [];
var needle = 100;
for (var i = 0; i < categoryGroups.length; i++) {
var subCategory = categoryGroups[i]['Categories'];
for (var j = 0; j < subCategory.length; j++) {
if (subCategory[j]['Id'] == findId) {
filterVal.push({
catIndex : i,
subCatIndex : j,
id : needle
});
}
}
}
console.log(filterVal);
Here is solution using reduce:
var arr = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }, ] } ]
const findPositions = (id) => arr.reduce((r,c,i) => {
let indx = c.Categories.findIndex(({Id}) => Id == id)
return indx >=0 ? {mainIndex: i, categoryIndex: indx} : r
}, {})
console.log(findPositions(100)) // {mainIndex: 1, categoryIndex: 0}
console.log(findPositions(1)) // {mainIndex: 0, categoryIndex: 0}
console.log(findPositions(200)) // {mainIndex: 1, categoryIndex: 1}
console.log(findPositions(0)) // {}
Beside the given answers with fixt depth searh, you could take an recursive approach by checking the Categories property for nested structures.
function getPath(array, target) {
var path;
array.some(({ Id, Categories = [] }) => {
var temp;
if (Id === target) {
path = [Id];
return true;
}
temp = getPath(Categories, target);
if (temp) {
path = [Id, ...temp];
return true;
}
});
return path;
}
var array = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 },] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }] }];
console.log(getPath(array, 100));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Am having a problem to return match array between two array element, please any help is important
here is my code
$scope.MacA = [
{
name: '24:fd:52:c3:d8:35',
sector: 'A23'
},
{
name: '56:db:30:4b:57:45',
sector: 'It support'
},
{
name: 'b6:b6:76:6b:e9:00',
sector: 'A24'
},
{
name: 'e8:74:e6:a1:14:16',
sector: 'Vodafone Guest'
},
{
name: 'dc:4a:3e:b7:32:0e',
sector: 'Direct HP officejet'
}
,
{
name: '7c:4c:a5:32:13:29',
sector: 'skyb7'
}
]
and array 2 is
scope.match = ['dc:4a:3e:b7:32:0e','7c:4c:a5:32:13:29' ];
and here is the function that returns the match if found
$scope.getList = function(){
// $scope.wifiList = WifiService.list();
var c = $scope.MacA;
var m = WifiService.list();
for(var i = 0;i < c.length;i++) {
for(var j = i;j < m.length;j++) { // Notice the j = i;
if (c[i].name === m[j]) {
$scope.result = c[i].sector;
// $scope.result = 'Its working';
break;
} else {
$scope.result = "Sorry!";
}
};
};
return $scope.result;
}
You didn't specify what exactly you want as the result, but here is a possible version that looks for matches.
var result = [];
match.forEach(m => result.push(MacA.find(macA => macA.name === m)));
MacA = [
{
name: '24:fd:52:c3:d8:35',
sector: 'A23'
},
{
name: '56:db:30:4b:57:45',
sector: 'It support'
},
{
name: 'b6:b6:76:6b:e9:00',
sector: 'A24'
},
{
name: 'e8:74:e6:a1:14:16',
sector: 'Vodafone Guest'
},
{
name: 'dc:4a:3e:b7:32:0e',
sector: 'Direct HP officejet'
},
{
name: '7c:4c:a5:32:13:29',
sector: 'skyb7'
}
]
Match = ['dc:4a:3e:b7:32:0e','7c:4c:a5:32:13:29' ];
MacA.filter(({name}) => Match.includes(name)).map(({sector}) => sector)
// RETURNS // ["Direct HP officejet", "skyb7"]
SO, given your code above, something like this:
$scope.getList = function(){
return $scope.result = $scope.MacA.filter(({name}) => $scope.match.includes(name)).map(({sector}) => sector)
}
I've refactored some of your code.
$scope.getList = function(){
var devices = $scope.MacA;
var macList = WifiService.list();
var results = devices.reduce((acc, device) => acc.concat(macList.find(current.name)? [current.sector]:[]), []);
return results.length? $scope.results = results : $scope.results = 'Sorry!';
}
I am quite new to AngularJS and have been building the following:
app.js
$scope.inkomsten= [
{ name: 'Salaris',value:'500' },
{ name: 'Toeslag',value:'200' },
{ name: 'Inkomsten',value:'211' },
{ name: 'Weekend', value:'22' }
];
$scope.uitgiften= [
{ name: 'eten',value:'120'},
{ name: 'kat',value:'230'},
{ name: 'schildpad', value: '300'},
{ name: 'huur', value: '200'}
];
Now I would like to take the values of both of these object and substract them from each other!
So either have all the values of Inkomsten added to another and the ones from Uitgiften.. and then substract or individually(Which is prefered... So taking the value of uitgiften and then from inkomsten and substract them.)
I have been tinkering around with it but I can't seem to find a solution for it. Anyways, not in Angular :D
I hope you guys can help
Clarification:
Sorry. I would like to have
uitgiften.value[1]+uitgiften.value[2]+uitgiften.value[3]
and then inkomsten.value[1]+inkomsten.value[2]+inkomsten.value[3]
and then the outcome of these 2 summs would need to be outcomeInkomsten-outcomeUitgiften=endOutcome
Since your values are strings, you will need to cast them to numbers. Here's what I would do:
var result = 0;
$scope.inkomsten.forEach(function(item){
result += Number(item.value);
});
$scope.uitgiften.forEach(function(item){
result -= Number(item.value);
});
Since it is an array you could add a function to the Array prototype.
$scope.inkomsten= [
{ name: 'Salaris',value:'500' },
{ name: 'Toeslag',value:'200' },
{ name: 'Inkomsten',value:'211' },
{ name: 'Weekend', value:'22' }
];
$scope.uitgiften= [
{ name: 'eten',value:'120'},
{ name: 'kat',value:'230'},
{ name: 'schildpad', value: '300'},
{ name: 'huur', value: '200'}
];
Array.prototype.sum = function (prop) {
var total = 0;
for ( var i = 0, _len = this.length; i < _len; i++ ) {
total += parseInt(this[i][prop]);
}
return total;
}
$scope.endOutcome = $scope.inkomsten.sum("value") - $scope.uitgiften.sum("value");
The Fiddle:
http://jsfiddle.net/U3pVM/20778/
you can use array method reduce:
var $scope={};
$scope.inkomsten= [
{ name: 'Salaris',value:'500' },
{ name: 'Toeslag',value:'200' },
{ name: 'Inkomsten',value:'211' },
{ name: 'Weekend', value:'22' }
];
var res = $scope.inkomsten.reduce(function(total, current){
return total + Number(current.value);
}, 0)
console.log(res)
this will give you the numeric total of an Array;
and then you can do the same with second array, and subtract the two;
well you can use
var results=0;
for(i=0;i<$scope.inkomsten.length;i++){
results+=Number($scope.inkomsten[i].value);
}
for(i=0;i<$scope.uitgiften.length;i++){
results-=Number($scope.uitgiften[i].value);
}
console.log(results);
You can try this below code
$scope.inkomsten= [
{ name: 'Salaris',value:'500' },
{ name: 'Toeslag',value:'200' },
{ name: 'Inkomsten',value:'211' },
{ name: 'Weekend', value:'22' }
];
$scope.uitgiften= [
{ name: 'eten',value:'120'},
{ name: 'kat',value:'230'},
{ name: 'schildpad', value: '300'},
{ name: 'huur', value: '200'}
];
$scope.sum1 = 0;
$scope.sum2 = 0;
for(i in $scope.inkomsten){
$scope.sum1 = $scope.sum1 + parseInt($scope.inkomsten[i].value);
}
for(i in $scope.uitgiften){
$scope.sum2 = $scope.sum2 + parseInt($scope.uitgiften[i].value);
}
$scope.endOutcome = $scope.sum1 - $scope.sum2;
alert($scope.endOutcome);
I'm new to Ionic and trying to test my controller which is using a service but keep getting 'undefined' with '$scope.order', '$scope.stock' and all the functions included in my controller. I have tested the service separately all tests passing there but can't get my head around controller testing. I'm sure I'm doing something wrong. Would be grateful is somebody could guide me a little bit.
controller.js
angular.module('shop.controllers', [])
.controller('StockCtrl', function($scope, Stock) {
$scope.stock = Stock.all();
$scope.order = Stock.order();
$scope.showTotalPrice = function() {
$scope.total = Stock.total();
}
$scope.addToBasket = function(chatId){
Stock.update(chatId);
Stock.updateBasket(chatId);
}
});
service.js
angular.module('shop.services', [])
.factory('Stock', function() {
var order = [];
var prices = [];
var total = 0;
var items = [{
id: 0,
name: "Black Shoes",
price: 50,
quantity: 7
},
{
id: 1,
name: "Blue Shoes",
price: 10,
quantity: 2
},
{
id: 2,
name: "Green Shoes",
price: 14,
quantity: 5
},
{
id: 3,
name: "Red Flip Flops",
price: 9,
quantity: 6
}
}];
return {
all: function() {
return items;
},
get: function(itemId) {
for (var i = 0; i < items.length; i++) {
if (items[i].id === parseInt(itemId)) {
return items[i];
}
}
return null;
},
update: function(itemId) {
for (var i = 0; i < items.length; i++) {
if (items[i].id === parseInt(itemId)) {
return items[i].quantity -= 1;
}
}
return null;
},
updateBasket: function(itemId) {
for (var i = 0; i < items.length; i++) {
if (items[i].id === parseInt(itemId)) {
order.push({name: items[i].name, price: items[i].price});
prices.push(items[i].price);
}
}
return null;
},
order: function() {
return order;
},
total: function() {
return total = eval(prices.join('+'));
},
};
});
controller.spec.js
describe('Controllers', function(){
var scope;
var control;
var StockMock;
beforeEach(module('shop.controllers'));
beforeEach(function(){
StockMock = jasmine.createSpyObj('Stock', ['all', 'get', 'update', 'updateBasket', 'order'])
inject(function($rootScope, $controller){
scope = $rootScope.$new();
control = $controller('StockCtrl', {$scope: scope, Stock: StockMock});
});
});
it("should have a scope variable defined", function() {
expect(scope).toBeDefined();
});
});
I think your problem is here:
beforeEach(module('shop.controllers'));
You should add the application module instead of controller module.
beforeEach(module('shop'));
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.