Equivalent of set in ES6 to ES5 - javascript

I have a set over which I am iterating in ES6. I am trying to convert it to its equivalent in ES5. My build is getting failed because of ES6. That's why I am converting it to ES5.
Here's my code in ES6
service.getDevices = function (date) {
var result = [];
var deviceList = devices[date.getTime()];
for (let item of deviceList) { // browser compatibility: support for ECMA6
result.push({"deviceName": item});
}
return result;
}
I am getting error because of 'let'. I tried using for (var item in deviceList), it does not display the charts.
I also tried this:
for(var i = 0; i < deviceList.length(); i++){
result.push({"deviceName" : deviceList[i]});
}
Even this is not working for set. can someone help and tell me how to iterate over a set in ES5 and if that is not possible, is there any equivalent way of doing it?

This is a basic set es5 class that I have used variations on over the years.
function Set(items) {
this._data = {};
this.addItems(items);
}
Set.prototype.addItem = function(value) {
this._data[value] = true;
return this;
}
Set.prototype.removeItem = function(value) {
delete this._data[value];
return this;
}
Set.prototype.addItems = function(values) {
for (var i = 0; i < values.length; i++) {
this.addItem(values[i]);
}
return this;
}
Set.prototype.removeItems = function(values) {
for (var i = 0; i < values.length; i++) {
this.removeItem(values[i]);
}
return this;
}
Set.prototype.contains = function(value) {
return !!this._data[value];
}
Set.prototype.reset = function() {
this._data = {};
return this;
}
Set.prototype.data = function() {
return Object.keys(this._data);
}
Set.prototype.each = function(callback) {
var data = this.data();
for (var i = 0; i < data.length; i++) {
callback(data[i]);
}
}
var set = new Set(['a', 'b', 'c']);
console.log(set.addItems(['a', 'd', 'e']).removeItems(['b', 'e']).data());
console.log(set.contains('a'));
console.log(set.contains('e'));
set.each(console.log)

Why not just iterate through the data and map the result with Array#map.
result = deviceList.map(function (item) {
return { deviceName: item };
});

I think your problem with your second for example is just that length is a property and not a function so you shouldn't add () to the end of it. A working version of this might look like this:
for(var i = 0; i < deviceList.length; i++){
result.push({"deviceName" : deviceList[i]});
}
This assumes (as #grabantot pointed out) that deviceList is an array, however, if it's a Set then you need to use the deviceList.size property.
However, there is a more compatible version of your first for loop which is the forEach() function (which is available on Array and Set), like this:
deviceList.forEach(function (item) {
result.push({"deviceName": item});
});

Related

How to compare two arrays of objects to find the differences

Actually, I meet with an iterate problem when I compare two arrays of objects.
Array Old:
[{uuid:'a'}, {uuid:'b'}, {uuid:'c'}]
Array New:
[{uuid:'a'}, {uuid:'e'}, {uuid:'f'}]
what I am going to do is calling the api under the below logic:
compare 'new' with 'old' to get the result:
[{name:1, uuid:'e'}, {name:1, uuid:'f'}]
and then call the POST api one by one to add new uuid: 'e' and 'f'
compare 'new' with 'old' to get the result:
[{name:1, uuid:'b'},{name:1, uuid:'c'}]
and then call the Delete api one by one to delete uuid: 'b' and 'c'
I have tried the below code to find the difference, but it seems not correct:(need some help)
const postArr = [];
for (var i = 0; i < this.new.length; i++) {
for (var o = 0; o < this.old.length; o++) {
if (
this.new[i].uuid !==
this.old[o].uuid
) {
postArr.push(this.new[i]);
}
}
}
console.log(postArr);
with filter and mapping u can achive uniques in old array
var a=[{uuid:'a'}, {uuid:'b'}, {uuid:'c'}];
var b=[{uuid:'a'}, {uuid:'e'}, {uuid:'f'}];
var keys = ['uuid'];
console.log(findDifferences(a,b))
function findDifferences(objectA, objectB) {
var result = objectA.filter(function(o1){
return !objectB.some(function(o2){
return o1.uuid === o2.uuid;
});
}).map(function(o){
return keys.reduce(function(newo, name){
newo[name] = o[name];
return newo;
}, {});
});
return result;
}
Try this instead:
function difference(checkingArray, baseArray) {
let diff = [];
let found = 0;
for (let j = 0; j<checkingArray.length; j++) {
found = 0;
for (let i = 0; i<baseArray.length; i++) {
if (baseArray[i].uuid == checkingArray[j].uuid) {
found = 1;
break;
}
}
if (found == 0) {
for (let k = 0; k<diff.length; k++) {
if (diff[k].uuid == checkingArray[j].uuid) {
found = 1;
break;
}
}
if (found == 0) {
diff.push(checkingArray[j]);
}
}
}
return diff;
}
let old = [{uuid:'a'}, {uuid:'b'}, {uuid:'c'}];
let recent = [{uuid:'a'}, {uuid:'e'}, {uuid:'f'}];
let onlyOnNewArray = difference(recent, old); // returns elements only in recent array not in old array
let onlyOnOldArray = difference(old, recent); // returns elements only in old array not in recent array
console.log("only on old array", onlyOnOldArray);
console.log("only on recent array", onlyOnNewArray);

Arrays Splice Pop Shift Read

I create an array like so
var membersList = $('#chatbox_members' , avacweb_chat.doc.body).find('li');
var onlineUsers = [];
var offLineUsers = [];
for(var i =0;i<membersList.length;i++){
var name = $(membersList[i]).text().replace("#","");
onlineUsers.push(name);
}
alert(onlineUsers);
listedUsers would come out something like so [Mr.EasyBB,Tonight,Tomorrow,Gone];
Question is if I use a two for loops one outside a setInterval and one inside to compare-
var membersList = $('#chatbox_members' , _chat.doc.body).find('li');
var onlineUsers = [];
var offLineUsers= [];
for(var i =0;i<membersList.length;i++){
var name = $(membersList[i]).text().replace("#","");
onlineUsers.push(name);
}
var int = setInterval(function() {
var newMember = ('#chatbox_members' , _chat.doc.body).find('li');
for(var i =0;i<newMember.length;i++){
var name = $(newMember[i]).text().replace("#","");
offLineUsers.push(name);
}
Which then would get:
onlineUsers = [Mr.EasyBB,Tonight,Tomorrow,Gone];
offLineUsers = [Mr.EasyBB,Tonight];
So to get the offline users I want to basically replace onlineUsers with offLineUsers which then should return Tomorrow,Gone . Though I know that an object doesn't have the function to replace so how would I go about this?
I don't think the splice function would work since you need to have parameters, and pop or shift are beginning and end of array.
for(var i = 0 ; i < offLineUsers.length ; i++)
{
for(var j = 0 ; j < onlineUsers.length ; j++)
{
if(onlineUsers[j] == offLineUsers[i])
{
onlineUsers.splice(j,1);
}
}
}
Try this snippet.
If I have understand well, maybe that helps:
function bus_dup() {
for(var i = 0; i < offLineUsers.length; i++) {
onLineUsers.splice(onLineUsers.indexOf(offLineUsers[i]),1);
}
offLineUsers = [];
}
This should do what you are looking for on a modern browser, using array.filter
var onlineUsers = ["Mr.EasyBB", "Tonight", "Tomorrow", "Gone"];
var offLineUsers = ["Mr.EasyBB", "Tonight"];
function discord(online, offline) {
return online.filter(function (element) {
return offline.indexOf(element) === -1;
});
}
console.log(discord(onlineUsers, offLineUsers));
Output
["Tomorrow", "Gone"]
On jsfiddle
If you want the difference regardless of the order of attributes passed to the function then you could do this.
var onlineUsers = ["Mr.EasyBB", "Tonight", "Tomorrow", "Gone"];
var offLineUsers = ["Mr.EasyBB", "Tonight"];
function difference(array1, array2) {
var a = array1.filter(function (element) {
return array2.indexOf(element) === -1;
});
var b = array2.filter(function (element) {
return array1.indexOf(element) === -1;
});
return a.concat(b);
}
console.log(difference(onlineUsers, offLineUsers));
console.log(difference(offLineUsers, onlineUsers));
Output
["Tomorrow", "Gone"] 
["Tomorrow", "Gone"] 
On jsfiddle

Array length undefined after split

I'd like to split a string ("1,2,3") and return it as an int array so I wrote the following function:
function stringToIntArray(string) {
var split = {};
split = string.split(',');
var selected = {};
for (var i = 0; i <= split.length; i++) {
selected[i] = split[i];
}
return selected;
}
However split.length is always undefinied. Where's my mistake?
var selected = {};
doesn't build an array but an object, which has no length property.
You can fix your code by replacing it with
var selected = [];
If you want to return an array of numbers, you can change your code to
function stringToIntArray(string) {
var split = string.split(',');
var selected = [];
for (var i = 0; i < split.length; i++) {
selected.push(parseInt(split[i], 10));
}
return selected;
}
Note that I replaced <= with < in your loop.
Note also that for modern browsers, you can use the map function to make it simpler :
function stringToIntArray(string) {
return string.split(',').map(function(v){ return parseInt(v, 10) });
}

Regrouping javascript array

I have the below javascript array with me
var test =[{
Maths:{
ST1:10,
ST2:2,
ST3:15}
},
{
Science:{
ST1:50,
ST3:40}
}
]
I want to generate the array shown below out of this
var t = [{ST1:{
Maths:10,
Science:50
},
ST2:{
Maths:2,
Science:0
},
ST3:{
Maths:15,
Science:40
}
}]
I tried using the code shown below
for (var key in test) {
if (test.hasOwnProperty(key)) {
for (var key1 in test[key]){
//console.log(key1)}
var abc = test[key][key1];
for(var x in abc)
{
console.log(x+key1+abc[x])
}
}
}
}
I am new to this help me doing this.
This does mostly what you want...
var t = {};
for (var i = 0; i < test.length; i++) {
for (var name in test[i]) {
for (var level in test[i][name]) {
if (!t[level])
t[level] = {}
t[level][name] = test[i][name][level]
}
}
}
Only thing missing is to get the Science:0 for when a STx value is missing under a section.
DEMO: http://jsfiddle.net/eHwBC/
Result:
{
"ST1": {
"Maths": 10,
"Science": 50
},
"ST2": {
"Maths": 2
},
"ST3": {
"Maths": 15,
"Science": 40
}
}
Keep in mind that there's no guaranteed order when using for-in for enumeration.
If the labels (Math, Science, etc) are known in advance, then you can ensure that each object gets all labels.
If not, a separate loop can be done. Depending on the approach, it could be done before or after this main loop.
Do you know about JSON.stringify(t)?
It will convert an object literal to JSON.
Mozilla's documentation of this function is available at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify.
You can also read this blog article for further explanation
Try this:
var test =[{
Maths:{
ST1:10,
ST2:2,
ST3:15
}
},
{
Science:{
ST1:50,
ST3:40}
}
];
var result = [];
for(i = 0; i <= test.length; i++){
var resultRow = {};
for(key in test[i]){
for(subKey in test[i][key]){
if(resultRow[subKey] == undefined){
resultRow[subKey] = {};
}
resultRow[subKey][key] = test[i][key][subKey];
}
}
result.push(resultRow);
}
Try like below,
/* Iterator start */
var t = {};
for (var i = 0; i < test.length; i++) { //Iterate Maths, Science,..
for (var key in test[i]) { //Iterate Math
for (var iKey in test[i][key]) { //Iterate ST1, ST2, ST3
var s = (t.hasOwnProperty(iKey))?t[iKey]:createObject();
s[key] = test[i][key][iKey];
t[iKey] = s;
}
}
}
/* Iterator End */
p = [];
p.push(t);
//^- p is what you want
// Separate function so you can add more items later without changing logic
function createObject () {
return {'Maths' : 0, 'Science': 0};
}
DEMO and Proof below,

comparing javascript arrays

I would like a function that compares to arrays of javascript strings, and saving the values that didnt match in to a new array. At the moment im using a nested jquery foreach. But i think there are better ways than this?
$.each(imagesInUploadsFolder, function(i, outervalue){
$.each(imagesInDatabaseTable, function(i, innervalue){
if(outervalue == innervalue){
//match in both arrays...
}
});
});
How about this:
arr1.forEach( function ( elem ) {
if ( arr2.indexOf( elem ) > -1 ) {
// match...
}
});
where arr1 and arr2 are your two arrays...
(Btw, ES5 shim for IE8, of course...)
Here's a way using a JSON object and no jQuery, although the $.inArray() should work fine:
var imagesInUploadsFolder = [
'/path/to/img1.png',
'/path/to/img2.png',
'/path/to/img3.png'
];
var imagesInDatabaseTable = [
'/path/to/img1.jpg',
'/path/to/img2.png',
'/path/to/img4.png'
];
var database_json = JSON.stringify(imagesInDatabaseTable);
for (var i = 0; i < imagesInUploadsFolder.length; i++) {
console.log(imagesInUploadsFolder[i] + ' in ' + database_json);
if (database_json.indexOf(imagesInUploadsFolder[i]) > -1) {
console.log('In database: ' + imagesInUploadsFolder[i]);
} else {
console.log('Not in database: ' + imagesInUploadsFolder[i]);
}
}
http://jsfiddle.net/7nJPW/1/
EDIT
Actually, the JSON method isn't needed (?):
for (var i = 0; i < imagesInUploadsFolder.length; i++) {
console.log(imagesInUploadsFolder[i] + ' in ' + imagesInDatabaseTable);
if (imagesInDatabaseTable.indexOf(imagesInUploadsFolder[i]) > -1) {
console.log('In database: ' + imagesInUploadsFolder[i]);
} else {
console.log('Not in database: ' + imagesInUploadsFolder[i]);
}
}
http://jsfiddle.net/7nJPW/2/
Why not use foreach of pure javascript?
for (var i = 0; i < innervalue.length; i++) {
for (var j = 0; j < outervalue.length; j++){
if (innervalue[i] === outervalue[j])
// match
}
}
It is the most easier way i can think of right now :)
$.each(imagesInUploadsFolder, function(i, outervalue){
if($.inArray(imagesInDatabaseTable,outervalue)>-1){
//my operation
}
}
FYI: Actually inArray returns index of innermatch else -1. Just incase you need it.
Whether you use jQuery or for loops, straight-out comparison will be O(n2), since you'll need to compare each element of one array with every element of another array.
If the objects are comparable, you can sort the items using a suitable comparison function, then loop over the two arrays simultaneously, examining if one element is less than the other. If you're familiar with merge-sort, this is very similar to the merge step. Assuming the comparison function is O(1), sorting is O(nlog(n)), and the merge-like comparison loop is O(n), the total time complexity is O(nlog(n)), where "n" is the length of the larger array.
imagesInUploadsFolder.sort(imgCmp);
imagesInDatabaseTable.sort(imgCmp);
// diff will hold the difference of the arrays
var diff = [];
var i=0, j=0, cmp;
while (i < imagesInUploadsFolder.length && j < imagesInDatabaseTable.length) {
cmp = cmp(imagesInUploadsFolder[i], imagesInDatabaseTable[j]);
if (cmp < 0) {
// up[i] < db[j]
++i;
diff.append(imagesInUploadsFolder[i]);
} else if (cmp > 0) {
// up[i] > db[j]
++j;
diff.append(imagesInDatabaseTable[j]);
} else {
// up[i] == db[j]
++i; ++j;
}
}
// one of the arrays may still have items; if so, loop over it and add the items
if (i < imagesInUploadsFolder.length) {
for (; i < imagesInUploadsFolder.length; ++i) {
diff.append(imagesInUploadsFolder[i]);
}
} else if (j < imagesInDatabaseTable.length)) {
for (; i < imagesInDatabaseTable.length; ++i) {
diff.append(imagesInDatabaseTable[i]);
}
}
// diff now holds items that are in only one of the two arrays.
If you can define a suitable object ID function, you can create an ancillary data structure that holds a set of elements. If accessing object properties is O(f(n)) (for hashes, f ≈ 1; for balanced trees, f = log(n)), then this approach is O(n*f(n)), so it should have no worse complexity than the sort-and-compare approach. Untested and inefficient implementation:
function Set(from) {
this.elements = {};
this.size = 0;
if (from) {
for (var i=0; i < from.length) {
this.add(from[i]);
}
}
}
Set.prototype.each = function(f) {
var eltId;
foreach (eltId in this.elements) {
f(this.elements[eltId], eltId);
}
};
Set.prototype.clone = function() {
var clone = new Set();
this.each(function(obj, id) {
clone.add(obj);
});
return clone;
};
Set.prototype.contains = function(obj) {
return obj.uniqueId() in this.elements;
};
Set.prototype.add = function(obj) {
var objId = obj.uniqueId();
if (! (objId in this.elements)) {
++this.size;
this.elements[objId] = obj;
}
return this;
};
Set.prototype.remove = function(obj) {
var objId = obj.uniqueId();
if (objId in this.elements) {
--this.size;
delete this.elements[objId];
}
return this;
};
Set.prototype.union = function(other) {
other.each(function(elt, id) { this.add(elt); });
return this;
};
Set.prototype.sub = function(other) {
other.each(function (elt, id) {
this.remove(elt);
});
return this;
};
Set.prototype.diff = function(other) {
var mine = this.clone();
mine.sub(other);
var others = other.clone();
others.sub(this);
mine.union(others);
return mine;
};
Set.prototype.toArray = function(obj) {
var arr = [];
this.each(function(elt, id) {
arr.append(elt);
});
return arr;
};
var uploadsSet = new Set(imagesInUploadsFolder),
dbSet = new Set(imagesInDatabaseTable),
imagesInJustOne = uploadsSet.diff(dbSet);
If you want both the union and difference of the arrays, you can define a suitable method on Set to more efficiently calculate them instead of using Set.diff and Set.union separately.

Categories