Splicing Array Based on For Loop Iteration - javascript

I am trying to take an array ('selectedWorkshops'), and move objects in it to 'registeredWorkshops'. Then, I also want to remove those objects from both 'selectedWorkshops' and another array simply called 'workshops'.
See my codepen here: http://codepen.io/trueScript/pen/wBVqNN
Arrays:
var workshops = [
{
name: 'apples',
WorkshopId: '19'
},
{
name: 'oranges',
WorkshopId: '3b'
},
{
name: 'pears',
WorkshopId: 'x6'
},
{
name: 'pineapples',
WorkshopId: '55'
},
{
name: 'watermelons',
WorkshopId: '8v'
}
];
var selectedWorkshops = [
{
name: 'oranges',
WorkshopId: '3b'
},
{
name: 'watermelons',
WorkshopId: '8v'
},
{
name: 'pears',
WorkshopId: 'x6'
}
];
var registeredWorkshops = [];
Function that is supposed to move workshops to 'registeredWorkshops' and remove them from 'selectedWorkshops' and 'workshops':
flipWorkshops = function(){
var numberOfWorkshops = selectedWorkshops.length;
var X = 1;
for(var i = 0; i < numberOfWorkshops; i++ ){
registeredWorkshops.push(selectedWorkshops[i]);
for(var j = 0, arrayLength = workshops.length; j < arrayLength; j++) {
var selectedWorkshop = selectedWorkshops[i];
var originalWorkshop = workshops[j];
if(selectedWorkshop == originalWorkshop){
var matchingWorkshop = j;
workshops = workshops.splice(j, 1);
selectedWorkshops = selectedWorkshops.splice(i, 1);
}
}
}
};
flipWorkshops();
Why aren't the objects being properly spliced out of the 'workshop' and 'selectedWorkshops' arrays like they should be? What am I doing wrong?

"The splice() method adds/removes items to/from an array, and returns the removed item(s)." http://w3schools.com/jsref/jsref_splice.asp So, basically, you're reducing workshops to a single object, the removed array element.
Instead, change:
workshops = workshops.splice(j, 1);
selectedWorkshops = selectedWorkshops.splice(i, 1);
...to:
workshops.splice(j, 1);
selectedWorkshops.splice(i, 1);
JSFiddle
Maybe this is what you want:
var registeredWorkshops = [];
var flipWorkshops = function(){
var numberOfWorkshops = selectedWorkshops.length;
var X = 1;
for(var i = numberOfWorkshops - 1; i >= 0; i-- ){
registeredWorkshops.push(selectedWorkshops[i]);
var selectedWorkshop = selectedWorkshops[i];
for(var j = workshops.length - 1; j >= 0; j--) {
var originalWorkshop = workshops[j];
if(selectedWorkshop.name == originalWorkshop.name &&
selectedWorkshop.WorkshopId == originalWorkshop.WorkshopId){
var matchingWorkshop = j;
workshops.splice(j, 1);
selectedWorkshops.splice(i, 1);
}
}
}
};
flipWorkshops();
Fixed the splice, reversed the loop, as suggested by jwatts1980, moved the selectedWorkshop var out of the loop, and compared each object item, rather than comparing objects, since objects don't compare.
JSFiddle Tweaked
JSFiddle Object Compare Example

Related

How to combine two array objects if a key value matches in both arrays

I am trying to combine two array objects with different array objects based on flight key.
If the value is matched in a2, I want to merge it with a1 and create new array.
All data in a1 must be there and matched flight details must be added from a2 to a1.
Please help me to solve this.
a1 = [{'flight':'AF1223','oring':'CDF', 'Dest':'HNG'},{'flight':'XG23','oring':'HYD', 'Dest':'MMZ'},{'flight':'PK145','oring':'XYZ', 'Dest':'PEK'}]
a2 = [{'price':230,'avail':20,'flight':'AF1223'}, {'price':430,'avail':30,'flight':'DF43'},{'price':430,'avail':30,'flight':'XG23'} ]
combine array = [{'flight':'AF1223','oring':'CDF', 'Dest':'HNG','price':230,'avail':20},{'flight':'XG23','oring':'HYD', 'Dest':'MMZ'},{'flight':'PK145','oring':'XYZ', 'Dest':'PEK','price':430,'avail':30,}]
I am giving you a complete solution.
a = [
{'id':'A','oring':'CDF', 'Dest':'HNG'},
{'id':'B','oring':'HYD', 'Dest':'MMZ'},
{'id':'C','oring':'XYZ', 'Dest':'PEK'}];
b = [
{'id':'A','price':230,'avail':20,},
{'id':'D','price':430,'avail':30},
{'id':'B','price':430,'avail':30} ];
// put the object D into array a
for(var i=0;i<b.length;i++) {
var idb = b[i].id;
var idnotfound = true;
a.forEach(function(rowofa) {
var ida = rowofa.id;
if(ida == idb) {
idnotfound = false;
}
});
if(idnotfound){
a.push(b[i]);
}
}//for
//console.log('aa=>>',a);
//.......................................
//Match ids and then put all in array a
for(var i= 0;i<a.length;i++) {
var ida = a[i].id;
for(var j=0;j<b.length;j++) {
var idb = b[j].id;
if(ida == idb) {
a[i].avail = b[j].avail;
a[i].price = b[j].price;
}//if
} //for2
}//for1
console.log('aa=>',a);
The output will be
aa=> [ { id: 'A', oring: 'CDF', Dest: 'HNG', avail: 20, price: 230 },
{ id: 'B', oring: 'HYD', Dest: 'MMZ', avail: 30, price: 430 },
{ id: 'C', oring: 'XYZ', Dest: 'PEK' },
{ id: 'D', price: 430, avail: 30 } ]
You can iterate over two arrays and if match push object from array2 ito array1, something like..
var a1 = [{'flight':'AF1223','oring':'CDF', 'Dest':'HNG'},{'flight':'XG23','oring':'HYD', 'Dest':'MMZ'},{'flight':'PK145','oring':'XYZ', 'Dest':'PEK'}];
var a2 = [{'price':230,'avail':20,'flight':'AF1223'}, {'price':430,'avail':30,'flight':'DF43'},{'price':430,'avail':30,'flight':'XG23'} ];
var result = a1.slice(0);
for (var i = 0 ; i < result.length ; i++){
for (var j = 0; j < a2.length ; j++){
if (result[i].flight == a2[j].flight){
result[i].price = a2[j].price;
result[i].avail = a2[j].avail;
}
};
};
console.log(result);
To match your desired output you can do as follows;
var a1 = [{'flight':'AF1223','oring':'CDF', 'Dest':'HNG'},{'flight':'XG23','oring':'HYD', 'Dest':'MMZ'},{'flight':'PK145','oring':'XYZ', 'Dest':'PEK'}],
a2 = [{'price':230,'avail':20,'flight':'AF1223'}, {'price':430,'avail':30,'flight':'DF43'},{'price':430,'avail':30,'flight':'XG23'}],
result = a2.reduce((p,c) => (p[c.flight] && (p[c.flight] = Object.assign(p[c.flight],c)),p), a1.reduce((f,s) => (f[s.flight] = s,f),{}));
console.log(result);

array.push only the last variable in a for loop javascript

i'm actually asking myself why the following code is not working properly i found the solution but it's a bit tricky and i don't like this solution
Here is the code and the problem:
function powerSet( list ){
var set = [],
listSize = list.length,
combinationsCount = (1 << listSize),
combination;
for (var i = 1; i < combinationsCount ; i++ ){
var combination = [];
for (var j=0;j<listSize;j++){
if ((i & (1 << j))){
combination.push(list[j]);
}
}
set.push(combination);
}
return set;
}
function getDataChartSpe(map) {
var res = {};
for (var i in map) {
console.log("\n\n");
var dataSpe = {certif: false,
experience: 0,
expert: false,
grade: 1,
last: 100,
name: undefined
};
var compMatchList = [];
for (var j in map[i].comps_match) {
var tmp = map[i].comps_match[j];
compMatchList.push(tmp.name)
}
var tmpList = powerSet(compMatchList);
var lol = [];
lol.push(map[i].comps_match);
for (elem in tmpList) {
console.log("mdr elem === " + elem + " tmplist === " + tmpList);
var tmp = tmpList[elem];
dataSpe.name = tmpList[elem].join(" ");
lol[0].push(dataSpe);
}
console.log(lol);
}
return res;
}
now here is the still the same code but working well :
function powerSet( list ){
var set = [],
listSize = list.length,
combinationsCount = (1 << listSize),
combination;
for (var i = 1; i < combinationsCount ; i++ ){
var combination = [];
for (var j=0;j<listSize;j++){
if ((i & (1 << j))){
combination.push(list[j]);
}
}
set.push(combination);
}
return set;
}
function getDataChartSpe(map) {
var res = {};
var mapBis = JSON.parse(JSON.stringify(map));
for (var i in map) {
var compMatchList = [];
for (var j in map[i].comps_match) {
var tmp = map[i].comps_match[j];
compMatchList.push(tmp.name)
}
var tmpList = powerSet(compMatchList);
mapBis[i].comps_match = [];
for (elem in tmpList) {
tmpList[elem].sort();
mapBis[i].comps_match.push({certif: false,
experience: 0,
expert: false,
grade: 1,
last: 100,
name: tmpList[elem].join(", ")});
}
}
return mapBis;
}
Actually it's a bit disapointig for me because it's exactly the same but the 1st one doesn't work and the second one is working.
so if anyone can help me to understand what i'm doing wrong it'll be with pleasure
ps: i'm sorry if my english is a bit broken
In the first version, you build one dataSpe object and re-use it over and over again. Each time this runs:
lol[0].push(dataSpe);
you're pushing a reference to the same single object onto the array.
The second version of the function works because it builds a new object each time:
mapBis[i].comps_match.push({certif: false,
experience: 0,
expert: false,
grade: 1,
last: 100,
name: tmpList[elem].join(", ")});
That object literal passed to .push() will create a new, distinct object each time that code runs.

Add or remove element(s) to array

I have an existing array of objects :
existingArray = [
{object1: 'object1'},
{object2: 'object2'}
{object3: 'object3'},
]
I receive a new one :
newArray = [
{object2: 'object2'},
{object3: 'object3'},
{object4: 'object4'}
]
I want only to modify the existing one to get the new one as the result (push+splice)
Here is what I have for now (is there a better way ?)
for (var i = 0; i < newArray.length; i++) {
// loop first to push new elements
var responseToTxt = JSON.stringify(newArray[i]);
var newStatement = false;
for(var j = 0; j < existingArray.length; j++){
var statementToTxt = JSON.stringify(existingArray[j]);
if(statementToTxt === responseToTxt && !newStatement){
newStatement = true;
}
}
if(!newStatement){
statements.push(response[i]);
}
}
var statementsToSplice = [];
for (var i = 0; i < existingArray.length; i++) {
// then loop a second time to split elements not anymore on the new array
var statementToTxt = JSON.stringify(existingArray[i]);
var elementPresent = false;
var element = false;
for(var j = 0; j < newArray.length; j++){
var responseToTxt = JSON.stringify(newArray[j]);
if(responseToTxt === statementToTxt && !elementPresent){
elementPresent = true;
} else {
element = i;
}
}
if(!elementPresent){
statementsToSplice.push(element);
}
}
Then I needed to split multiple times in the array :
existingArray = statementsToSplice.reduceRight(function (arr, it) {
arr.splice(it, 1);
return arr;
}, existingArray.sort(function (a, b) { return b - a }));
Here is the example :
https://jsfiddle.net/docmz22b/
So the final output should always be the new array, but only by push or splice the old one.
In this case, the final outpout will be
existingArray = [
{object2: 'object2'},
{object3: 'object3'}
{object4: 'object4'},
]
The new array could contains multiple new elements and/or deleted elements that is currently in the existingArray
Use shift() and push()
existingArray.shift(); //Removes the first element of the array
existingArray.push({'object4' : 'object4'});
Fiddle
I'm almost 100% sure that there is a better way to do it, but at least this works, feel free to comment any suggestions / optimizations.
existingArray = [
{object1: 'object1'},
{object2: 'object2'},
{object3: 'object3'}
];
newArray = [
{object2: 'object2'},
{object3: 'object3'},
{object4: 'object4'}
];
// Loop all the old values, if is not in the new array, remove it
existingArray.forEach(function(item) {
if(!inArray(item, newArray)) {
var idx = indexOfObjectInArray(item, existingArray);
existingArray.splice(idx, 1);
}
});
// Loop all the new values, if is not in the new array, push it
newArray.forEach(function(item) {
if (!inArray(item, existingArray)) {
existingArray.push(item);
}
});
// Auxiliar functions
function inArray(initialValue, array) {
testValue = JSON.stringify(initialValue);
return array.some(function(item) {
return testValue == JSON.stringify(item);
});
}
function indexOfObjectInArray(initialValue, array) {
var result = -1;
testValue = JSON.stringify(initialValue);
array.forEach(function(item, idx) {
if (testValue == JSON.stringify(item)) {
result = idx;
};
});
return result;
}
Maybe this helps. It features Array.prototype.forEach and Array.prototype.some.
Splice unwanted items
Look if object with same property exist
If yes, then assign new object
Else push the object
var existingArray = [
{ object1: 'object1' },
{ object2: 'object2' },
{ object3: 'object3' },
],
newArray = [
{ object2: 'object22' },
{ object3: 'object33' },
{ object4: 'object44' }
];
function update(base, change) {
var changeKeys = change.map(function (a) { return Object.keys(a)[0]; }),
i = 0;
while (i < base.length) {
if (!~changeKeys.indexOf(Object.keys(base[i])[0])) {
base.splice(i, 1);
continue;
}
i++;
}
change.forEach(function (a) {
var aKey = Object.keys(a)[0];
!base.some(function (b, i, bb) {
if (aKey === Object.keys(b)[0]) {
bb[i] = a; // if that does not work, use bb.splice(i, 1, a);
return true;
}
}) && base.push(a);
});
}
update(existingArray, newArray);
document.write('<pre>' + JSON.stringify(existingArray, 0, 4) + '</pre>');

Comparing an Array with an Objects' Array in JavaScript

I am new to JavaScript and wondering how can I compare an array with another array consists of JavaScript objects.
The array is a series of sorted time in the "YYYY-MM-DD" format.
The array of objects missed some price values of several days.
I want to find the missed value and assign it as "NULL".
For example, I have an array as:
array = ['2014-10-09','2014-10-10','2014-10-11','2014-10-12'];
and an array with objects as:
objArray = [{
date:"2014-10-09",
price:"100"
},
{
date:"2014-10-10",
price:"99"
},
{
date:"2014-10-12",
price:"102"
}];
I want to get the price array in this way:
priceResult = [100, 99, "NULL", 102];
What would be the most efficient way without using other libraries? I wanted to see if anyone had a more elegant solution. I deeply appreciate your help.
You can create a lookup set from the object array, then you can use that to translate the dates to prices.
This scales well, as it is an O(n+m) solution rather than the O(n*m) solution that you get if you use a loop in a loop to find the prices.
var array = ['2014-10-09','2014-10-10','2014-10-11','2014-10-12'];
var objArray = [{ date:"2014-10-09", model:"A", price:"100" },{ date:"2014-10-10", model:"A", price:"99" },{ date:"2014-10-12", model:"A", price:"102" }];
var lookup = {};
for (var i = 0; i < objArray.length; i++) {
lookup[objArray[i].date] = parseInt(objArray[i].price, 10);
}
var priceResult = [];
for (var i = 0; i < array.length; i++) {
if (lookup.hasOwnProperty(array[i])) {
priceResult.push(lookup[array[i]]);
} else {
priceResult.push('NULL');
}
}
// output result in StackOverflow snippet
document.write(JSON.stringify(priceResult));
Note: Instead of the string 'NULL' you might want to use the value null instead, as it is generally easier to handle.
lodash is the best library for this. But you did say "without using other libraries", so you will need to do it natively.
The easiest way to do it is nested for loops:
var i, j, d, res = [];
for (i=0; i<dateArray.length; i++) {
d = dateArray[i];
for (j=0; j<objArray.length; j++) {
if (objArray[j] && objArray[j].date && objArray[j].date === d) {
res.push(objArray[j].price);
j = objArray.length; // don't waste energy searching any more, since we found it
}
}
}
// res now contains all you wanted
If objArray is really big, and you don't want to search it multiple times, then you could turn it into an object indexed by date:
var i, obj = {}, d, res = [];
for (i=0; i<objArray.length; i++) {
if (objArray[i] && objArray[i].date) {
obj[objArray[i].date] = objArray[i];
}
}
for (i=0; i<dateArray.length; i++) {
d = dateArray[i];
res.push(obj[d] ? obj[d].price : null : null);
}
// res now contains all you wanted
Loop trough the object and search for the date in your array
// Add contains to array proto: http://css-tricks.com/snippets/javascript/javascript-array-contains/
var priceResult = [];
for(var i in objArray) {
if(dateArray.contains(objArray[i].date)) priceResult.push(objArray[i].date));
}
console.log('matches:', priceResult);
This function will give you map of all individual arrays in your object array
function getArrayMap(array) {
var map={}
for(var i=0;i<array.length;i++){
var o = array[i];
for(var k in o){
if(!map[k]){
map[k]=[];
}
map[k].push(o[k]);
}
}
return map;
}
you can use it like -
var map = getArrayMap(objArray);
console.log(map["date"]);//date array
console.log(map["price"]);//price array
console.log(map["model"]);//model array
If i am understanding your question correctly, for all the values in array, you want to check the objArr and find the price for each date, and if not found u want to inset null. If this is what you want, then following will help
var found= false;
var list=[];
for(var i=0; i< dateArray.length; i++)
{
for(var j=0; j< objArray.length; j++)
{
if(objArray[j].date == dateArray[i])
{
list.push(objArray[j].price);
found = true;
}
}
if(!found)
{
list.push("null");
}
found = false;
}
alert(list);
(I'm going to call your first array dates rather than array, to avoid confusion.)
There are basically two options:
Loop through your dates array and, for each entry, loop through the objArray looking for a match, and when found add to your priceResult array, or
Build a map from your objArray, then loop through yourdatesarray once, building thepriceResult` array.
Looping and Looping
You can loop through your dates array using forEach, and you can use Array#some to find out whether your objArray contains the date and add to priceResult if so (it's an ES5 feature, but you can polyfill it for really old browsers):
var priceResult = [];
dates.forEach(function(date) {
objArray.some(function(object) {
if (object.date == date) {
priceResult.push(object.price);
return true;
}
});
});
Array#some keeps looping until you return true, which is why we do that when we find the firs tmatch. That's why I say this is "looping and looping," even though we only write one loop, the other is within Array#some.
var dates = ['2014-10-09', '2014-10-10', '2014-10-11', '2014-10-12'];
var objArray = [
{
date: "2014-10-09",
model: "A",
price: "100"
},
{
date: "2014-10-10",
model: "A",
price: "99"
},
{
date: "2014-10-12",
model: "A",
price: "102"
}
];
// Do it
var priceResult = [];
dates.forEach(function(date) {
objArray.some(function(object) {
if (object.date == date) {
priceResult.push(object.price);
return true;
}
});
});
snippet.log(priceResult.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Mapping and Looping
First, create a map of prices by date:
var prices = {};
objArray.forEach(function(object) {
prices[object.date] = object.price;
});
...then create your results:
var priceResult = [];
dates.forEach(function(date) {
if (prices.hasOwnProperty(date)) {
priceResult.push(prices[date]);
}
});
var dates = ['2014-10-09', '2014-10-10', '2014-10-11', '2014-10-12'];
var objArray = [
{
date: "2014-10-09",
model: "A",
price: "100"
},
{
date: "2014-10-10",
model: "A",
price: "99"
},
{
date: "2014-10-12",
model: "A",
price: "102"
}
];
// Create the map
var prices = {};
objArray.forEach(function(object) {
prices[object.date] = object.price;
});
// Create your results:
var priceResult = [];
dates.forEach(function(date) {
if (prices.hasOwnProperty(date)) {
priceResult.push(prices[date]);
}
});
// Show them
snippet.log(priceResult.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
var dates = ['2014-10-09','2014-10-10','2014-10-11','2014-10-12'];
var objArray = [{date:"2014-10-09", model:"A", price:"100" }, {date:"2014-10-10", model:"A", price:"99" }, {date:"2014-10-12", model:"A", price:"102" }];
var val;
var priceResult = [];
for (var a in dates) {
val = null;
for (var b in objArray) {
if (dates[a] == objArray[b].date) {
val = objArray[b].price;
}
}
priceResult.push(val);
}
var dates = ['2014-10-09', '2014-10-10', '2014-10-11', '2014-10-12'];
var objArray = [{
date: "2014-10-09",
model: "A",
price: "100"
}, {
date: "2014-10-10",
model: "A",
price: "99"
}, {
date: "2014-10-12",
model: "A",
price: "102"
}];
var val;
var priceResult = [];
for (var a in dates) {
val = null;
for (var b in objArray) {
if (dates[a] == objArray[b].date) {
val = objArray[b].price;
}
}
priceResult.push(val);
}
// output result in StackOverflow snippet
document.write(JSON.stringify(priceResult));
Try this:
var temp[]
temp= jQuery.grep(objArray , function (n, i)
{
for(j=0;j<dateArray.lenght+j++ )
if( n.date === dateArray[j])
return n.price;
);
dateArray = ["2014-10-09", "2014-10-10", "2014-10-11", "2014-10-12"];
function ObjectExample(date1,model,price)
{
this.date1 = date1;
this.model = model;
this.price = price;
}
var objArray = [new ObjectExample("2014-10-09","A","100"), new ObjectExample("2014-10-10","A","99"), new ObjectExample("2014-10-12","A","102")];
var i = 0;
var priceDate = new Array();
var count = 0;
while(i < dateArray.length)
{
var j = 0;
while(j < objArray.length)
{
if(dateArray[i] == objArray[j].date1)
{
priceDate[count] = objArray[j].price;
break;
}
else priceDate[count] = "NULL";
j = j + 1;
}
i = i + 1;
count++;
}
document.write(priceDate);

Given two Arrays - contacts() & contactsSelected() - How to match the two?

I have two arrays (contacts & contactsSelected) both with the following type of structure:
{
id: 1,
name: bob
},
{
id: 213,
name: Rob
}
I'm using KnockoutJS. How Can I iterate over contacts() and for each row, determine if that row's ID is contained in the contactsSelected array? In KnockoutJS I have something like this:
userCardModel.contactsToShow = ko.dependentObservable(function () {
return ko.utils.arrayFilter(this.contacts(), function(contact) {
return /////////////// LOGIC GOES HERE TO See if this contact.id() is contained in the contactsSelected() array
});
}, userCardModel);
Thanks
OK, you could do it like so...
var contactsSelectedLength = contacts.length;
for (var i = 0, contactsLength = contacts.length; i++) {
var contact = contacts[i];
for (var j = 0; j < contactsSelectedLength; j++) {
var selectedContact = contactsSelected[j];
if (contact.id == selectedContact.id) {
// It is in there!
}
}
}
Add the IDs of "contactsSelected" as properties of an object so they can be accessed in better-than-linear time using the "in" operator or "hasOwnProperty" method:
var getSelectedIds = function(sel) {
var len=sel.length, o={}, i;
for (i=0; i<len; i++) {
o[sel[i].id] = true;
}
return o;
};
var selectedIds = getSelectedIds(contactsSelected);
(1 in selectedIds); // => true
(2 in selectedIds); // => false
selectedIds.hasOwnProperty(213); // => true
selectedIds.hasOwnProperty(214); // => false

Categories

Resources