javascript looping changing values of other objects - javascript

for (var i = 0; i < itemArray.length; i++) {
//console.log(itemArray[index].mats);
var newMatArray = [];
for (var j = 0; j < itemArray[i].mats.length; j++) {
var mat = itemArray[i].mats[j];
if (isInNewArray(mat.id, newMatArray)) {
continue;
}
for (var k = 0; k < itemArray[i].mats.length; k++) {
var mat2 = itemArray[i].mats[k];
if (k == j) {
continue;
}
if (mat.id == mat2.id) {
//if (itemArray[i].id == 12005) console.log("adding " + mat.quantity + " of " + mat.name + " to " + mat2.quantity);
mat.quantity = mat.quantity + mat2.quantity;
}
}
newMatArray.push(mat);
}
//if (itemArray[i].id == 12005) console.log(newMatArray);
itemArray[i].mats = newMatArray;
}
function isInNewArray(id, array) {
for (var i = 0; i < array.length; i++) {
if (array[i].id == id) {
return true;
}
}
return false;
}
So this loop is supposed to iterate over an array of items and remove/combine duplicate mats required for an item, each item is a json object with a name/id and a mats array of objects and each mat has a name/id/quantity required. For some reason if i iterate over only 1 item at some point in the array then continue on all the rest without combining it works totally fine.
It's only when its looping that changing the values of previous objects seems to change the value of future objects resulting in mats hitting quantities of 1.17555e^105 which is way higher than they should be. Does javascript do some kind of memory optimization that might be storing mat objects with identical values to the same location so when i increase the quantity on objects earlier in the loop it does so for objects later in the loop? Otherwise I don't understand why this algorithim works for 1 off objects but looping over objects and only ever changing one object at a time messes it up.
Edit: sample object below
{
"id": 622,
"bpid": 692,
"quantity": 1,
"name": "Stabber",
"mats": [
{
"id": 34,
"name": "Tritanium",
"quantity": 48518335
},
{
"id": 35,
"name": "Pyerite",
"quantity": 11828791
},
{
"id": 36,
"name": "Mexallon",
"quantity": 40000
},
{
"id": 37,
"name": "Isogen",
"quantity": 10333
},
{
"id": 38,
"name": "Nocxium",
"quantity": 2778
},
{
"id": 39,
"name": "Zydrine",
"quantity": 1244
},
{
"id": 40,
"name": "Megacyte",
"quantity": 244
},
{
"id": 20411,
"name": "Datacore - High Energy Physics",
"quantity": 8
},
{
"id": 20172,
"name": "Datacore - Minmatar Starship Engineering",
"quantity": 8
}
]
}
for (var i = 0; i < matsArray.length; i++) {
var item = matsArray[i];
var type = parseInt(item.typeID, 10);
var index = findItemIndex(type);
if (index > -1) {
var mat = {
id: parseInt(item.materialTypeID, 10),
name: itemIDMap.get(parseInt(item.materialTypeID, 10)),
quantity: parseInt(item.quantity, 10)
}
itemArray[index].mats.push(mat);
} else {
if (bpMap.get(parseInt(item.typeID, 10)) == undefined) {
//console.log(item);
continue;
}
var newItem = {
id: bpMap.get(parseInt(item.typeID, 10)).itemID,
bpid: parseInt(item.typeID, 10),
quantity: bpMap.get(parseInt(item.typeID, 10)).quantityPerRun,
name: itemIDMap.get(bpMap.get(parseInt(item.typeID, 10)).itemID),
mats: []
}
var mat = {
id: parseInt(item.materialTypeID, 10),
name: itemIDMap.get(parseInt(item.materialTypeID, 10)),
quantity: parseInt(item.quantity, 10)
}
newItem.mats.push(mat);
itemArray.push(newItem);
productsArray.push(newItem.id);
}
}
Would this array creation code create identical mat objects? Shouldn't each newly created mat be a separate object?

Related

Group array of objects by key and compare grouped result with date array

How to group array of objects to array with key indexname and compare with dates array
var data= [
{
"indexname": "red",
"data": [
{
"date": "2018-09-07",
"count": 3
}
]
},
{
"indexname": "red",
"data": [
{
"date": "2018-09-05",
"count": 2
}
]
},
{
"indexname": "red",
"data": [
{
"date": "2018-09-06",
"count": 10
}
]
},
{
"indexname": "yellow",
"data": [
{
"date": "2018-09-07",
"count": 6
}
]
}
]
var dates=['2018-08-09','2018-08-07','2018-09-07','2018-09-01','2018-09-06','2018-09-05','2018-09-04','2018-09-03','2018-09-02']
var grouped = _.mapValues(_.groupBy(data.results, 'indexname'),
clist => clist.map(index => _.omit(index, 'indexname')));
required format
var result=[['date','red','yellow'],[2018-08-09,0,0],[2018-08-07,0,0],[2018-09-07,3,6],[2018-09-06,10,0],[2018-09-05,5,0],[2018-09-04,0,0],[2018-09-03,0,0],[2018-09-02,0,0],]
I have an array of object and dates array i want to get the following result
How to acheive this?
Here is the pure javascript representation for the output result you want. Might be improved for 1 or 2 less loops:
var data = [{
"indexname": "red",
"data": [{
"date": "2018-09-07",
"count": 3
}]
},
{
"indexname": "red",
"data": [{
"date": "2018-09-05",
"count": 2
}]
},
{
"indexname": "red",
"data": [{
"date": "2018-09-06",
"count": 10
}]
},
{
"indexname": "yellow",
"data": [{
"date": "2018-09-07",
"count": 6
}]
}
];
var dates = ['2018-08-09', '2018-08-07', '2018-09-07', '2018-09-01', '2018-09-06', '2018-09-05', '2018-09-04', '2018-09-03', '2018-09-02'];
//Prepair index1 of final array an push to see how many colors are present
var index1 = ['date'];
var colors_sorted_arr = [];
var dates_sorted_arr = [];
//Push data to index1 for colors
for (var i = 0; i < data.length; i++) {
if (index1.indexOf(data[i].indexname) == -1) {
index1.push(data[i].indexname)
}
}
//Seperate out data according to color wise
for (var i = 0; i < data.length; i++) {
for (var j = 1; j < index1.length; j++) {
if (data[i].indexname == index1[j]) {
if (colors_sorted_arr[(j - 1)] == undefined) {
colors_sorted_arr[(j - 1)] = [];
colors_sorted_arr[(j - 1)].push(data[i].data[0]);
} else {
colors_sorted_arr[(j - 1)].push(data[i].data[0]);
}
}
}
}
//Now push index1 data to final array
dates_sorted_arr[0] = index1;
//For other data to final array loop through dates array , then inside that loop through all colors
//and then for all colors loop inside each value to check for particular data
for (var i = 0; i < dates.length; i++) {
dates_sorted_arr[(i + 1)] = [];
dates_sorted_arr[(i + 1)].push(dates[i]);
for (var j = 0; j < colors_sorted_arr.length; j++) {
for (var k = 0; k < colors_sorted_arr[j].length; k++) {
if (colors_sorted_arr[j][k].date == dates[i]) {
dates_sorted_arr[(i + 1)].push(colors_sorted_arr[j][k].count);
}
}
}
for (var l = 0; l < index1.length; l++) {
if (dates_sorted_arr[(i + 1)].length != index1.length) {
dates_sorted_arr[(i + 1)].push(0);
}
}
}
//After creating above got final result what you want
console.log(dates_sorted_arr);

Looping between functions and storing results

I would like produce a list of grouped JSON elements according to a specific criteria, but I am unable to make my loop work.
The function should make groups of with 12 bottles and return a single JSON list. So in this example, the function should extract the 3 first items and then run again to extract the remaining ones. But I am looping forever... Thank you in advance,
var data = {
"order": [
{ "product": "MAXIMUS", "quantity": "3" },
{ "product": "COLECCION", "quantity": "3" },
{ "product": "CABERNET FRANC", "quantity": "6" },
{ "product": "CHARDONNAY", "quantity": "6" },
{ "product": "SAUVIGNON BLANC", "quantity": "6" }
]
};
var qtd = data.order;
var size = qtd.length;
var addline = '';
var add = '';
var total = 0;
var i = 0;
var a = 0;
var c = '';
function MakeList(i, add) {
for (i < 0; total < 12; i++) {
total += parseInt(qtd[i].quantity);
addline = addline + '{' + '"quantity": "' + qtd[i].quantity + ' units"},';
i = i++;
add = '{"Box of 12":[' + addline.slice(0, -1) + "]}";
}
return [i, add];
}
function BuildLabels(i, add) {
for (i < 0; c = "true"; i++) {
c = a[0] < size;
a += MakeList(i, add);
i = i++;
}
return a;
}
var results = BuildLabels(i, add);
output = { id: 3, results };
for (i < 0; c = "true"; i++)
something weird is happening here. You don't set any condition on cycle to stop, you just assign value "true" to c. Try to use == instead of =; also initialization looks strange - set i to 0. Apparently, It will make the whole thing work (at least the loop will stop at some point), but in the end I get that the variable results is equal to 0. There are other mistakes/weird stuff out there. Propably, you wanted to achieve something like this:
var data = {
"order": [
{ "product": "MAXIMUS", "quantity": "3" },
{ "product": "COLECCION", "quantity": "3" },
{ "product": "CABERNET FRANC", "quantity": "6" },
{ "product": "CHARDONNAY", "quantity": "6" },
{ "product": "SAUVIGNON BLANC", "quantity": "6" }
]
};
function MakeList(data) {
var selected = [], bottlesNum = 0;
for (var i = 0; bottlesNum < 12; i++) {
selected.push(data.order[i]);
bottlesNum += parseInt(data.order[i].quantity);
}
return selected;
}
var results = MakeList(data);
// now it is a JS object:
console.log({ id: 3, results: results });
// if you want it to be a JSON string, use JSON.stringify():
console.log(JSON.stringify({ id: 3, results: results }));
check it out.
UPDATE
var data = {
"order": [
{ "product": "MAXIMUS", "quantity": "3" },
{ "product": "COLECCION", "quantity": "3" },
{ "product": "CABERNET FRANC", "quantity": "6" },
{ "product": "CHARDONNAY", "quantity": "6" },
{ "product": "SAUVIGNON BLANC", "quantity": "6" }
]
};
function makeGroup(data, max) {
var selected = [], bottlesNum = 0;
while(data.order.length) {
if(bottlesNum + +data.order[0].quantity > max) break;
var order = data.order.shift();
bottlesNum += +order.quantity; // casting to Number
selected.push(order);
}
return selected;
}
function splitOrder(data, max) {
while(data.order.length) {
var results = makeGroup(data, max);
if(!results.length) {
console.log("Error: a product's quantity is greater than max. size of the group. Try to increase max. size of the group.");
break;
}
console.log({ results: results });
}
}
// 2nd argument - max. size of the group. In case of 12 there will be 2 groups - of 3, 3, 6 and 6, 6 bottles
splitOrder(data, 12);
// Also notice that if max. size of the group is a changing value and can be set somehow to, lets say, 4 which is fewer than number of some products (6) in our order. So, it is impossible to complete such a task without taking some additional steps to handle this situation. For example, we could filter our data beforehand to exclude products with numbars greater than 4 and then form groups based on the rest of the data. Or we can treat products with number equal to 6 as if they satisfy our constraint etc.

Remove Multiple Objects from the group of Array

I would like to splice the whole Object inside the array "Docs > Exam" which has "Pass":"NO"
i have tried this
var docs = [
{"Id":1,"Name":"First","Exam":[{"Pass":"No"},{"Sub":"T1"}]},
{"Id":2,"Name":"Second","Exam":[{"Pass":"Yes"},{"Sub":"T2"}]},
{"Id":3,"Name":"Third","Exam":[{"Pass":"No"},{"Sub":"T3"}]}
];
for (var i = docs.length - 1; i >= 0; i--) {
for (var j = docs[i].Exam.length - 1; j >= 0; j--) {
if (docs[i].Exam[j].Pass == 'No') {
docs.splice(docs[i],1);
}
}
}
console.log(docs);
I need only the docs with this object only
{"Id":2,"Name":"Second","Exam":[{"Pass":"Yes"},{"Sub":"T2"}
This is very easy using filter and some:
docs = docs.filter(doc => doc.Exam.some(exam => exam.Pass === 'Yes'))
const isExamPassed = exam => exam.Pass === 'Yes';
1. docs.filter(doc => isExamPassed(doc.Exam[0]));
2. docs.map(doc => doc.Exam[0])
.filter(isExamPassed);
Use Array.filter API.
var docs = [{
"Id": 1,
"Name": "First",
"Exam": [{
"Pass": "No"
}, {
"Sub": "T1"
}]
},
{
"Id": 2,
"Name": "Second",
"Exam": [{
"Pass": "Yes"
}, {
"Sub": "T2"
}]
},
{
"Id": 3,
"Name": "Third",
"Exam": [{
"Pass": "No"
}, {
"Sub": "T3"
}]
}
];
console.log("Before Filtering: ", docs.length);
docs = docs.filter(function(doc, index) {
var bIsPass = true;
for (var j = doc.Exam.length - 1; j >= 0; --j) {
if (doc.Exam[j].Pass === "No") {
bIsPass = false;
break;
}
}
return bIsPass;
});
console.log("Before Filtering: ", docs.length);
console.log("Result :", docs);

aggregate in nested ng-repeat

I want to create a sum of taskAssembly.labour of each taskAssembly object and put it in the totalLabour field
see this plunker. http://plnkr.co/edit/rKnup0IIPRYvh8JLHXbD?p=preview
see my data:
{ "client": "client1","takeoff": [{
"taskName": "ToW",
"taskQnt": 2300,
"totalLabour":"",
"taskAssembly": [
{
"taskName": "ToW",
"taskQnt": 2300,
"taskLabour": 22,
"taskAssembly": [
{ "qnt": 2300, "product": "non-INT", "labour": 12, "application": "spray" },
{ "qnt": 2300, "product": "non-INT", "labour": 10, "application": "strips" }
]
},
{
"taskName": "Pens",
"taskQnt": 43,
"taskLabour": 23,
"taskAssembly": [
{ "qnt": 43, "product": "non-INT", "labour": 23, "application": "spray" }
]
}
]}
my code is not exactly doing what I need.
$scope.getTotalLabour = function(){
var total = 0;
for(var i = 0; i < $scope.estimate.takeoff.length; i++){
var item = $scope.estimate.takeoff[i];
total += (item.taskLabour);
}
return $scope.estimate.totalLabour = total;
}
any idea of how I can do this?
Check working demo: JSFiddle
Simply create a nested loop like:
for(var i = 0; i < $scope.estimate.takeoff.length; i++){
var total = 0;
var item = $scope.estimate.takeoff[i];
console.log(item);
for (var j = 0; j < item.taskAssembly.length; j++) {
total += (item.taskAssembly[j].labour);
}
item.totalLabour = total;
}

Compare two objects in jQuery and get the difference [duplicate]

This question already has answers here:
How to get the difference between two arrays in JavaScript?
(84 answers)
Closed 7 years ago.
Using jQuery I would like to compare 2 objects:
sourceArray:
var origArray = [{
"Name": "Single",
"URL": "xxx",
"ID": 123
},
{
"Name": "Double",
"URL": "yyy",
"ID": 345
},
{
"Name": "Family",
"URL": "zzz",
"ID": 567
}];
destination array
var destArray = [{
"Name": "Single",
"URL": "xxx",
"ID": 123
},
{
"Name": "Double",
"URL": "yyy",
"ID": 888
},
{
"Name": "Family",
"URL": "zzz",
"ID": 567
}];
What I would like to do, is compare the target object with the source object based on the ID and find the mis-matched entries with a description on the resultant object. So the result will look like this:
var resultArray = [{
"Name": "Double",
"URL": "yyy",
"ID": 888,
"desc": "missing in source"
},
{
"Name": "Double",
"URL": "yyy",
"ID": 345,
"desc": "missing in destination"
}];
Any quick help is really appreciated.
This isn't a good use of jQuery, but here is some vanilla javascript that does what you want.
function objDiff(array1, array2) {
var resultArray = []
array2.forEach(function(destObj) {
var check = array1.some(function(origObj) {
if(origObj.ID == destObj.ID) return true
})
if(!check) {
destObj.desc = 'missing in source'
resultArray.push(destObj)
}
})
array1.forEach(function(origObj) {
var check = array2.some(function(destObj) {
if(origObj.ID == destObj.ID) return true
})
if(!check) {
origObj.desc = 'missing in destination'
resultArray.push(origObj)
}
})
return resultArray
}
https://jsfiddle.net/9gaxsLbz/1/
If you are wanting to dedupe your array, this will work:
var merged = origArray.concat(destArray);
var unique = merged.filter(function(item) {
return ~this.indexOf(item.ID) ? false : this.push(item.ID);
}, []);
Fiddle: https://jsfiddle.net/Ljzor9c6/
If you are only wanting items that were duped, you can easily invert the condition:
var merged = origArray.concat(destArray);
var dupes = merged.filter(function(item) {
return ~this.indexOf(item.ID) ? true : !this.push(item.ID);
}, []);
You can loop through the items in the first array and put the ID's in a map, then loop through the items in the second array and remove the matching ID's and add the missing.
Then just loop through the map to create the objects in the resulting array:
var origArray = [{
"Name": "Single",
"URL": "xxx",
"ID": 123
},
{
"Name": "Double",
"URL": "yyy",
"ID": 345
},
{
"Name": "Family",
"URL": "zzz",
"ID": 567
}];
var destArray = [{
"Name": "Single",
"URL": "xxx",
"ID": 123
},
{
"Name": "Double",
"URL": "yyy",
"ID": 888
},
{
"Name": "Family",
"URL": "zzz",
"ID": 567
}];
var map = {};
for (var i = 0; i < origArray.length; i++) {
map[origArray[i].ID] = 'source';
}
for (var i = 0; i < destArray.length; i++) {
var id = destArray[i].ID;
if (id in map) {
delete map[id];
} else {
map[id] = 'destination';
}
}
var resultArray = [];
for (key in map) {
var arr = map[key] == 'source' ? origArray : destArray;
for (var i = 0; arr[i].ID != key; i++) ;
resultArray.push({
Name: arr[i].Name,
URL: arr[i].URL,
ID: arr[i].ID,
desc: 'missing in ' + map[key]
});
}
// show result in StackOverflow snippet
document.write(JSON.stringify(resultArray));
var result = [];
for(var i = 0; i < oa.length; i++) {
var idx = mIndexOf(oa[i].ID);
if(idx > -1) {
oa.splice(i, 1);
da.splice(idx, 1);
}
}
for(var i = 0; i < oa.length; i++) {
var ln = result.length;
result[ln] = oa[i];
result[ln].desc = "missing in destination";
}
for(var i = 0; i < da.length; i++) {
var ln = result.length;
result[ln] = da[i];
result[ln].desc = "missing in origin";
}
function mIndexOf(id) {
for(var i = 0; i < oa.length; i++)
if(oa[i].ID == id)
return i;
return -1;
}
console.log(result);
0: Object
ID: 345
Name: "Double"
URL: "yyy"
desc: "missing in destination"
1: Object
ID: 888
Name: "Double"
URL: "yyy"
desc: "missing in origin"
jsfiddle DEMO
For things like this, you should use lodash. With lodash you can just do this:
var resultArray = _.defaults(destArray, origArray);

Categories

Resources