Merge two arrays of arrays by ID in AppsScript - javascript

I have two arrays in an App Script project, one with a user email and their last login date, and one with their email and license type. I'd like to combine these two arrays into an array where each item has their email, last login, and license.
It's not guaranteed that the arrays will be in the same order.
Example:
Array 1: [[google.user#domain.com, Google-Apps, 1010020020],[google.user2#domain.com, Google-Apps, 1010020020]
Array 2: [[google.user2#domain.com, 12/31/1969],[google.user#domain.com, 12/31/1969]]
becomes
Array 3: [[google.user#domain.com, 12/31/1969, Google-Apps, 1010020020],[google.user2#domain.com, 12/31/1969, Google-Apps, 1010020020]]
I tried several of the methods described in this post and this post but they seem to be ES6 and throw errors when I run them.

In es5, your code should be like this:
var a1 = [['google.user#domain.com', 'Google-Apps', '1010020020'],['google.user2#domain.com', 'Google-Apps', '1010020020']]
var a2 =[['google.user#domain.com', '12/31/1969'],['google.user2#domain.com', '12/31/1969
var a3 = new Array()
for(var i=0;i<a1.length;i++){
a3[i]=new Array();
a3[i][0]=a1[i][0];
a3[i][2]=a1[i][1];
a3[i][3]=a1[i][2];
}
for(var i=0;i<a2.length;i++){
for(var j=0;i<a3.length;j++){
if(a3[j][0] == a2[i][0]){
a3[j][1] = a2[i][1];
break;
}
}
}

Related

Why is my code behaving like I have duplicate keys in a dictionary despite using unique strings? Javascript / Appscript

I am trying to loop through a dictionary of customers and save energy usage data, but for some customers when I try to change the values in their usage dictionary it will also change a completely different customer's value. I have a nested dictionary with customer utility information, the top-level key being a unique internal ID.
I stripped my code down to a single loop, looping through the top-level keys and setting the same month's usage for all customers in the dictionary to be the value of the iterator. After that, as shown in the code sample below, I log the values for three customers. After that, I increment only one of those customer's usage, and log the values again. The console shows that two over the customer's have dictionaries that are tied together somehow, but I can't figure out why or how to solve this. I can't discern any pattern in the keys of the linked customers, either.
Structure of the nested dictionary:
CustDict =
{"N0100000XXXXXX" =
{"name" = "XXXX"},
{"address" = "XXXX"},
{"meter_read_dates" =
{"2021-05-13" =
{"usage" = "XXXX"}
}
}
}
Stripped down code I used to demonstrate what is happening as simply as possible (real ID values):
Logger.log(custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000000419887"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000012580668"]["meter_read_dates"]["2021-05-13"]["usage"])
custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"] =
custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"] + 1
Logger.log(custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000000419887"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000012580668"]["meter_read_dates"]["2021-05-13"]["usage"])
Console Output:
11:54:56 AM Info 346.0
11:54:56 AM Info 346.0
11:54:56 AM Info 322.0
11:54:56 AM Info 347.0
11:54:56 AM Info 347.0
11:54:56 AM Info 322.0
Code used to create the CustDict dictionary:
stmtCR = conn.prepareStatement('SELECT cust_id, utility_account, cycle_id, read_cycle FROM customers')
results = stmtCR.executeQuery()
resultsMetaData = results.getMetaData()
numCols = resultsMetaData.getColumnCount();
results.last();
numRows = results.getRow();
i = 0
results.first()
var custDict = {}
while (i < numRows)
{
custDict[results.getString(1)] = {}
custDict[results.getString(1)]["id"] = results.getString(1)
custDict[results.getString(1)]["utility_account"] = results.getString(2)
custDict[results.getString(1)]["cycle_id"] = results.getString(3)
custDict[results.getString(1)]["read_cycle"] = results.getString(4)
results.next()
i++;
}
for (i = 0; i < Object.keys(custDict).length; i++)
{
tempCust = custDict[Object.keys(custDict)[i]]
tempCycleId = tempCust["cycle_id"]
tempReadCycle = tempCust["read_cycle"]
tempCust["meter_read_dates"] = cycleIdShdDict[tempCycleId][tempReadCycle]
custDict[Object.keys(custDict)[i]] = tempCust
}
cycleIdShdDict is a seperate dictionary that contains a set of dates associated with each cycle_id and read_cycle
I suspect the problem is that Object.keys(custDict) is returning the keys in a different order at different places in the for loop. So you're getting the object from one key, and then assigning it to a different key.
There's no need to assign back to custDict[Object.keys(custDict)[i]] since you're modifying the object in place, not a copy.
But instead of looping through the keys, loop through the values and modify them.
Object.values(custDict).forEach(tempCust => {
let tempCycleId = tempCust["cycle_id"];
let tempReadCycle = tempCust["read_cycle"];
tempCust["meter_read_dates"] = cycleIdShdDict[tempCycleId][tempReadCycle];
});

How to push object to array in angularjs?

This is my code
$scope.studentDetails=[];
$scope.studentIds={};
$scope.studentIds[0]{"id":"101"}
$scope.studentIds[1]{"id":"102"}
$scope.studentIds[2]{"id":"103"}
in the above code when i select student id:101 i got marks from services like
$scope.studentMarks={};
$scope.studentMarks[0]{"marks":"67"}
$scope.studentMarks[1]{"marks":"34"}
next i select student id:102 i got marks from services like
$scope.studentMarks={};
$scope.studentMarks[0]{"marks":"98"}
$scope.studentMarks[1]{"marks":"85"}
finally i want to store student details in to one array like
$scope.studentDetails=[{"id":"101","marks":[67,34]},{"id":"102","marks":[98,85]}]
using angularjs.
Seems like its more of a JS question than angular.
What about the Javascript push method?
$scope.studentDetails.push({id: 101, marks: [67, 34]});
You can use Array.push to add one object, or concat, to concat array into another array. See the references.
angularJS is just a library to extend Javascript. You push into an array just like you would any object in Javascript.
First off, you need to declare an array.
$scope.studentIds = []; // Array of student ids.
Then when you want to add, you push:
$scope.studentIds.push({id: "101"});
To do this naively you need to loop through the student ids and then loop through the marks object and adding it to your studentDetails object if the ids match:
var studentDetails = [];
for (var id in studentIds) {
var studentDetail = {}; // this will be a single student
var marks = [];
if (studentIds.hasOwnProperty(id)) {
for (var mark in studentMarks) {
if (studentMarks.hasOwnProperty(mark) && mark.id === id) {
studentDetail.id = id;
marks.push(mark.marks);
}
}
studentDetail.marks = marks;
}
studentDetails.push(studentDetail);
}
$scope.studentDetails = studentDetails;

JS and ExpressionEngine - Remove KV pairs by duplicate values only?

We're building a site with ExpressionEngine. We are running a SQL query to gather up all member IDs for a specific member group. After that, we are using EE tags to get data from a custom member field for each member ID.
The ID and field data need to stay paired, as we will be populating a drop-down so that the ID is the value and the field data is the text, so we are currently putting them into a JS array as key/value pairs. The call is as follows:
var array= [
{exp:query sql="SELECT * FROM exp_members WHERE group_id = 5"}
{exp:member:custom_profile_data
member_id="{member_id}"}
{if company != ''}
{{member_id}:"{company}"},
{/if}
{/exp:member:custom_profile_data}
{/exp:query}
};
This gives us the output:
var array = [
{1:"name01"},
{2:"name02"},
{3:"name01"},
{4:"name03"}
];
Now, our problem. We need to remove objects based on duplicate field data (values) only, so the above array would look like this:
var array = [
{1:"name01"},
{2:"name02"},
{4:"name03"}
];
None of these IDs (keys) will ever be the same, but the field data (values) can be. So we want to keep the first KV pair that comes through with a unique value, but remove any subsequent dupes of that value - despite the fact that they will not be true "duplicate values" due to a different ID (key).
Keeping in mind that the KV pairs are all dynamic, is there any possible way to do this via JS so we can create a new array for the cleaned data to pass to the drop-down?
You could handle the duplications by modifying your MySQL query. (In my example, my custom field ID was 1.)
var myArray = [];
{exp:query sql="SELECT MIN(m.member_id) AS co_member_id, d.m_field_id_1 AS company FROM exp_members m INNER JOIN exp_member_data d ON m.member_id = d.member_id WHERE d.m_field_id_1 != '' AND m.group_id > 0 GROUP BY d.m_field_id_1;"}
myArray.push({{co_member_id}: "{company}"});
{/exp:query}
This query would use the first (in the ordinal sense) member_id found; you could also change the MIN to MAX and get the last.
This will give you a clean output in your source, without the need for any additional JS processing. I'd also recommend changing the names of the variables you're outputting as to not conflict in EE's parsing.
I would do it like...
function removeDups(arry){
var tmp = {}, retainIdx=[], newArry=[];
arry.forEach(function(obj, idx){
var val = obj[Object.keys(obj)[0]];
if(val && !tmp[val]){
retainIdx.push(idx);
tmp[val] = true;
}
});
retainIdx.forEach(function(i){
newArry.push(arry[i]);
});
return newArry;
};

compare two arrays and return duplicate values

How may I retrieve an element that exists in two different arrays of the same document.
For example. In Posts collection, document has the fields 'interestbycreator' and 'interestbyreader.' Each field contain user Ids.
'interestbycreator': //an array of ids here. IdA, idB, IdC, IdD, IdE,
'interestbyreader': //an array of ids here. IdB, idE, iDF
Basically I wish to find all the ids that exist in both arrays, so that should be IdB and IdE.
I am able to pluck all the values from an array with underscore and store them in a variable. Can they be compared to each other this way and return duplicates? Or can someone shed some light on another solution.
Example to retrieve all Ids from 'interestbyreader
var interestbypostcreater = Posts.find({_id: Meteor.user().profile.postcreated[0]}, {fields: {interestbyreader: 1}}).fetch();
var interestedReaderIds = _.chain(interestbypostcreator).pluck('interestbyreader').flatten().value();
Assume I have the other array 'interestbycreator' stored in a variable called interestIdcreator, can they be compared to find duplicates and return these duplicates?
As saimeunt said in the comments when you have access to underscore use intersection but you can also do it with plain javascript:
var x = ['IdA', 'idB', 'IdC', 'IdD', 'IdE'];
var y = ['idB', 'IdE', 'IdF'];
var z = x.filter(function(val) {
return y.indexOf(val) != -1;
});
console.log(z);
The array z contains the double entries then.
Credits to https://stackoverflow.com/a/14930567/441907
As Saimeunt pointed out, it can be done as
var x = ['IdA', 'idB', 'IdC', 'IdD', 'IdE'];
var y = ['idB', 'IdE', 'IdF'];
var z = _.intersection(x, y);

How to build an associative array with jQuery/javascript?

I have a large array in this format:
var cars = [{"brand":"Honda","year":"2002"},{"brand":"Toyota","year":"2000"},{"brand":"Subaru","year":"2009"}];
The array is very large (I made it small for demo purpose) and I want to organize cars of the same brand into an array, so the brand name will be the key for each sub-array, like this:
carsByBrand[ honda[], toyota[], subaru[] ]
I expected it would be straight forward but it's not so. I've tried several variations of the following code, but everytime it returns:
carsByBrand[item.brand] is undefined
var carsByBrand = [];
$.each(cars, function(i,item){
carsByBrand[item.brand].push(item);
});
//console.debug(carsByBrand); //uncomment and look at this if you have Firebug
alert(carsByBrand.length);
I've also tried carsByBrand[item['brand']], why doesn't this work, and how to do it?
jsBin: http://jsbin.com/orafos
carsByBrand[item.brand].push(item);
That will only work if the array for that brand already exists, which it does not unless you initialize it first with an empty array.
Try
brand = carsByBrand[item.brand];
if (brand) {
brand.push(item);
else {
carsByBrand[item.brand] = [item];
}

Categories

Resources