I'd be grateful if someone can explain what I'm doing wrong here. I compare two arrays of geographic coordinates, successfully find the common elements and then try to get the indexes for the first hit. Only arrB works as expected. Although the key is quite clearly at arrA[1], no match is found. I've included loads of logging because I don't quite believe what I'm seeing.
function arrayIntersect(a, b) {
/* credit https://stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript */
var aa = {};
a.forEach(function(v) { aa[v]=1; });
return b.filter(function(v) { return v in aa; });
}
const arrA = [[53.88,-2.96],[53.7,-2.45],[53.79,-2.52],[53.66,-2.61],[53.98,-2.34],[53.92,-2.36],[53.89,-2.95],[53.9,-2.94],[53.88,-2.4],[53.89,-2.81],[53.93,-2.77],[53.87,-2.13],[53.9,-2.54],[53.6,-2.91],[54.01,-2.83],[53.83,-2.44],[53.6,-2.88],[54.02,-2.76],[53.99,-2.8],[54.15,-2.79],[53.85,-2.13],[53.62,-2.96],[54,-2.84],[53.66,-2.75],[53.91,-2.27],[53.86,-2.62],[53.51,-2.13],[53.82,-2.3]]
const arrB = [[53.82,-2.9],[53.95,-2.73],[53.62,-2.73],[54.11,-2.81],[54.18,-2.84],[53.53,-2.09],[53.83,-2.98],[53.87,-2.42],[53.82,-2.66],[53.87,-2.41],[53.88,-2.98],[53.96,-2.75],[53.53,-2.02],[53.7,-2.45],[54.06,-2.87],[53.94,-2.34],[53.7,-2.87],[53.61,-2.89],[54.18,-2.84],[54.12,-2.8],[53.86,-2.82],[53.9,-2.53],[53.91,-2.86],[53.81,-2.26],[53.8,-2.51],[53.79,-2.98],[53.79,-3],[53.74,-2.92],[54.11,-2.8],[53.96,-2.49],[53.89,-2.44],[53.87,-2.12],[53.93,-2.77],[53.93,-2.78],[53.86,-2.86],[54.14,-2.46],[54.08,-2.78],[54.07,-2.75],[53.94,-2.86],[53.78,-3],[54.02,-2.89],[53.86,-2.26],[53.68,-2.79],[53.66,-2.75],[53.66,-2.88],[53.78,-2.79],[53.66,-2.31],[53.67,-2.3],[53.6,-2.08],[53.63,-2.09],[54.16,-2.83],[53.62,-2.96],[53.84,-2.15]]
console.log(arrA.length + ' ' + Array.isArray(arrA))
console.log(arrB.length + ' ' + Array.isArray(arrB))
console.log(arrA[0].length + ' ' + Array.isArray(arrA[0])) // sample entries
console.log(arrB[0].length + ' ' + Array.isArray(arrB[0]))
res = arrayIntersect(arrA, arrB) ; console.log('res ' + res + ' ' + Array.isArray(res))
let key = res[0] ; console.log('key ' + key + ' ' + Array.isArray(key))
let idxA = arrA.indexOf(key) ; console.log('idxA ' + idxA)
let idxB = arrB.indexOf(key) ; console.log('idxB ' + idxB)
Results
Server started at http://localhost:8080
28 true
53 true
2 true
2 true
res 53.7,-2.45,53.93,-2.77,53.66,-2.75,53.62,-2.96 true
key 53.7,-2.45 true
idxA -1
idxB 13
When you use arrays with objects in it the indexOf function compares then the object reference and not the object itself to get the index value. And remember, in your case you have arrays in arrays but in javascript also arrays are objects so this aplies as well in your case.
Then your arrayIntersect function filters arrB, therefor the originale objects from arrB are stored then in the res array which then only can be used to get back the index in the arrB.
One approach could be to just use find for arrA to get the index and just stringify the objects while comparing:
function arrayIntersect(a, b) {
/* credit https://stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript */
var aa = {};
a.forEach(function(v) { aa[v]=1; });
return b.filter(function(v) { return v in aa; });
}
const arrA = [[53.88,-2.96],[53.7,-2.45],[53.79,-2.52],[53.66,-2.61],[53.98,-2.34],[53.92,-2.36],[53.89,-2.95],[53.9,-2.94],[53.88,-2.4],[53.89,-2.81],[53.93,-2.77],[53.87,-2.13],[53.9,-2.54],[53.6,-2.91],[54.01,-2.83],[53.83,-2.44],[53.6,-2.88],[54.02,-2.76],[53.99,-2.8],[54.15,-2.79],[53.85,-2.13],[53.62,-2.96],[54,-2.84],[53.66,-2.75],[53.91,-2.27],[53.86,-2.62],[53.51,-2.13],[53.82,-2.3]]
const arrB = [[53.82,-2.9],[53.95,-2.73],[53.62,-2.73],[54.11,-2.81],[54.18,-2.84],[53.53,-2.09],[53.83,-2.98],[53.87,-2.42],[53.82,-2.66],[53.87,-2.41],[53.88,-2.98],[53.96,-2.75],[53.53,-2.02],[53.7,-2.45],[54.06,-2.87],[53.94,-2.34],[53.7,-2.87],[53.61,-2.89],[54.18,-2.84],[54.12,-2.8],[53.86,-2.82],[53.9,-2.53],[53.91,-2.86],[53.81,-2.26],[53.8,-2.51],[53.79,-2.98],[53.79,-3],[53.74,-2.92],[54.11,-2.8],[53.96,-2.49],[53.89,-2.44],[53.87,-2.12],[53.93,-2.77],[53.93,-2.78],[53.86,-2.86],[54.14,-2.46],[54.08,-2.78],[54.07,-2.75],[53.94,-2.86],[53.78,-3],[54.02,-2.89],[53.86,-2.26],[53.68,-2.79],[53.66,-2.75],[53.66,-2.88],[53.78,-2.79],[53.66,-2.31],[53.67,-2.3],[53.6,-2.08],[53.63,-2.09],[54.16,-2.83],[53.62,-2.96],[53.84,-2.15]]
console.log(arrA.length + ' ' + Array.isArray(arrA))
console.log(arrB.length + ' ' + Array.isArray(arrB))
console.log(arrA[0].length + ' ' + Array.isArray(arrA[0])) // sample entries
console.log(arrB[0].length + ' ' + Array.isArray(arrB[0]))
res = arrayIntersect(arrA, arrB) ; console.log('res ' + res + ' ' + Array.isArray(res))
let key = res[0] ; console.log('key ' + key + ' ' + Array.isArray(key))
let idxA = arrA.indexOf(arrA.find(el=>JSON.stringify(el)===JSON.stringify(key))) ; console.log('idxA ' + idxA)
let idxB = arrB.indexOf(key) ; console.log('idxB ' + idxB)
Related
I need to insert values in the next row after executing this script. The difference between the rows is 13.
How I would I loop this script so that after execution, the values appear in the next row?
// Google Sheets API
const GoogleSpreadsheet = require('google-spreadsheet');
const {promisify} = require('util');
const creds = require('./client_secret.json');
var counter = 0; // Used to debug cellnumber association
// Define Spreadhseet Scope
const cells = await promisify(sheet.getCells)({
'min-row': 1,
'max-row': 106,
'min-col': 1,
'max-col': 13,
'return-empty': true
});
// Get a list of all the cells and relate them to a counter for assigning variables
for(const cell of cells){
counter++;
console.log(`${counter-1} -- ${cell.row}, ${cell.col}: ${cell.value}`);
}
/* Assign all variables to related spreadsheet cell */
cells[17].value = value + '%';
cells[17].save();
cells[18].value = value + '%';
cells[18].save();
cells[19].value = value+ '%';
cells[19].save();
cells[20].value = value+ '%' ;
cells[20].save();
cells[21].value = value+ '%';
cells[21].save();
cells[22].value = value + '%';
cells[22].save();
}
sendToGoogleSpreadsheet();
PYTHON
I am making a calculator that displays formulas and answers of a few different things after you enter time, distance, mass, etc. Velocity works fine, but Speed and Acceleration are display apostrophes, commas, and parentheses. Some of them aren't even in the editor.
Output:
('Speed = Distance / Time = 1m / 1s', ' = 1m/s')
('Acceleration = Force / Mass = 1N', ' / 1kg = 1.0m/s/s')
Velocity = Speed + Direction = 1m/s + Direction = 1m/s North
The variables in the program:
SpeedFormula = 'Speed = Distance / Time = ' + distanceDisplay + ' / ' + timeDisplay, ' = ' + speedDisplay
AccelerationFormula = 'Acceleration = Force / Mass = ' + forceDisplay, ' / ' + massDisplay + ' = ' + AccelerationDisplay
VelocityFormula = 'Velocity = Speed + Direction = ' + speedDisplay + " + " + 'Direction' + ' = ' + VelocityDisplay
Anyone know why they display differently and how I can fix it?
Replace
timeDisplay, ' = ' + speedDisplay
with
timeDisplay + ' = ' + speedDisplay
When you use comma SpeedFormula becomes a tuple, not a string.
P.S. You should probably use formatting like this:
distanceDisplay = 20
timeDisplay = 2
speedDisplay = 10
SpeedFormula = 'Speed = Distance / Time = %d / %d = %d' % (distanceDisplay,timeDisplay,speedDisplay)
On my BeagleBone Black, when I run this script:
#!/usr/bin/node
var b = require('bonescript');
b.getPlatform(printData);
function printData(x) {
console.log('name = ' + x.name);
console.log('version = ' + x.version);
console.log('serialNumber = ' + x.serialNumber);
console.log('bonescript = ' + x.bonescript);
console.log();
}
b.pinMode("P9_11", b.OUTPUT, 7, 'pullup', 'slow');
b.pinMode("P9_13", b.OUTPUT, 7, 'pullup', 'slow');
b.pinMode("P9_15", b.OUTPUT, 7, 'pullup', 'slow');
b.pinMode("P9_17", b.OUTPUT, 7, 'pullup', 'slow');
b.getPinMode("P9_11", printPinMux);
b.getPinMode("P9_13", printPinMux);
b.getPinMode("P9_15", printPinMux);
b.getPinMode("P9_17", printPinMux);
function printPinMux(x) {
console.log('mux = ' + x.mux);
console.log('pullup = ' + x.pullup);
console.log('slew = ' + x.slew);
if(x.options) {
console.log('options = ' + x.options.join(','));
}
console.log('pin = ' + x.pin);
console.log('name = ' + x.name);
console.log('err = ' + x.err);
console.log();
}
I get this output:
name = BeagleBone Black
version = 0A5A
serialNumber = 1813BBBK7710
bonescript = 0.2
mux = 7
pullup = pullup
slew = fast
options = gpmc_wait0,mii2_crs,NA,rmii2_crs_dv,mmc1_sdcd,NA,NA,gpio0_30
pin = P9_11
name = UART4_RXD
err = undefined
mux = 7
pullup = pullup
slew = fast
options = gpmc_wpn,mii2_rxerr,NA,rmii2_rxerr,mmc2_sdcd,NA,NA,gpio0_31
pin = P9_13
name = UART4_TXD
err = undefined
mux = 2
pullup = pulldown
slew = slow
options = spi0_cs0,mmc2_sdwp,i2c1_scl,NA,NA,NA,NA,gpio0_5
pin = P9_17
name = I2C1_SCL
err = undefined
mux = 0
pullup = pulldown
slew = fast
options = mii1_rxd3,NA,rgmii1_rd3,mmc0_dat5,mmc1_dat2,NA,mcasp0_axr0,gpio2_18
pin = P9_15
name = GPIO1_16
err = undefined
It looks like b.pinMode() isn't setting the pins' modes. Why?
So I have this javascript function:
function show_courseline (course_index, repeats) {
var s = "";
var count = 0;
while (count < repeats) {
s = s + 'Number: ' + document.getElementById(course_index + count + 'a').innerHTML + '\n' +
'Semester: ' + document.getElementById(course_index + count + 'b').innerHTML + '\n' +
'Year: ' + document.getElementById(course_index + count + 'c').innerHTML + '\n' +
'Title: ' + document.getElementById(course_index + count + 'd').innerHTML + '\n' +
'Units: ' + document.getElementById(course_index + count + 'e').innerHTML + '\n' +
'Description: ' + document.getElementById(course_index + count + 'f').innerHTML + '\n';
++count;
}
alert(s);
}
But I get an error when I run it through an "onclick" input box. It has nothing to do with the document ids not being there, because they are.
Is course_index integer? If it is course_index + count is an integer and I know that ids cannot start with a digit
I am hoping someone can put me out of my misery here. I rewrote a LotusScript function in JavaScript and it is not working as it should be. I can't look at this thing anymore. I"m hoping someone can help me figure this out.
The function takes a name of a group and an address book db object. It fetches and returns all the members of that group including nested groups. It works great in the Lotusscript version but not in the Javascript version. It's something to do with the recursive function and the index into the array's.
If you create two groups. Put 10 names in the first group and 5 names in the second group. Note, Name the second group with a leading # to make it sort to the top of the first group
group-A
1group-A
bla
bla2
bla3
bla4
bla5
bla6
bla7
bla8
bla9
bla10
1group-A
other1
other2
other3
other4
other5
In the Javascript version when you pass the function group-A it returns 10 names. Five from the second group and the second five from the first group.
Here is the code for the lotusscript version
Function LibGetGroupMembers( groupName As String, addressBook As NotesDatabase ) As Variant
' This Function takes a passed in group name and gets all the members of that group.
' Not a big whoop until you consider nested group names. This is a recursive routine.
'
' Inputs : Name of the group to fetch the members of.
'
' Uses : Global objects
'
' Outputs : Returns an array of members
'
' History:
' 02.19.2001 - Steven Rieger : Created Function.
Dim groupView As NotesView
Dim groupMainDoc As NotesDocument
Dim groupMembers As Variant
Dim nestedGroupMembers As Variant
Dim arrayOfMembers() As String
Dim mainIndex As Integer
Dim nestedIndex As Integer
Dim resultIndex As Integer
On Error Goto ErrorHandling
gLibObjectName = CStr( GetThreadInfo(1) ) & " - " & gLibDatabaseNamePath
gLibErrorMessage = "Begin " & gLibObjectName
Call LibLogErrorPushCallingPgm ( gLibErrorMessage )
Print( gLibErrorMessage )
gLibAdditionalErrorMessage = "Fetching Group View From NAB"
Set groupView = addressBook.GetView( "($VIMGroups)" )
If( groupView Is Nothing ) Then
Call LibLogError( "Error: Un-able to get view from address book", gLibErrorMessage )
Exit Function
End If
gLibAdditionalErrorMessage = "Fetching Group Main Document " & groupName
Set groupMainDoc = groupView.GetDocumentByKey( groupName, True )
resultIndex = 0
Redim arrayOfMembers( 0 )
' Did we find a matching group document?
If Not( groupMainDoc Is Nothing ) Then
If Not( Iselement ( gListOfGroupNames( Lcase( groupName ) ) ) ) Then
' Print( "Processing Group: " & groupName )
gListOfGroupNames( Lcase( groupName ) ) = " "
groupMembers=groupMainDoc.GetItemValue( "Members" )
For mainIndex = Lbound( groupMembers ) To Ubound( groupMembers)
nestedGroupMembers= LibGetGroupMembers( groupMembers( mainIndex ), addressBook )
If( nestedGroupMembers(0) = "" ) Then
If( groupMembers( mainIndex ) <> "" ) Then
Redim Preserve arrayOfMembers( Ubound( arrayOfMembers ) + 1)
arrayOfMembers( resultIndex ) = groupMembers( mainIndex )
resultIndex = resultIndex + 1
End If
Else
Redim Preserve arrayOfMembers( Ubound( nestedGroupMembers ) + resultIndex )
For nestedIndex = Lbound( nestedGroupMembers ) To Ubound( nestedGroupMembers )
arrayOfMembers( resultIndex ) = nestedGroupMembers( nestedIndex )
resultIndex = resultIndex + 1
Next
End If
Next
If( arrayOfMembers( Ubound( arrayOfMembers ) ) = "" And Ubound( arrayOfMembers ) > 0 ) Then
Redim Preserve arrayOfMembers( Ubound( arrayOfMembers ) - 1 )
End If
Else
groupName = "*** Circular Group: " & groupName & " ***"
End If
End If
LibGetGroupMembers = arrayOfMembers
Goto Bye
ErrorHandling :
Call LibLogError( "Error: " & Err( ) & ": " & Error( ) & Chr( 13 ) & Chr( 13 ) & "Occured in Module " & CStr( GetThreadInfo(1) ) & " at Line Number: " & Erl(), CStr( GetThreadInfo(1) & " - " & gLibDatabaseNamePath ) )
Resume Bye
Bye:
gLibAdditionalErrorMessage = "End " & CStr( GetThreadInfo(1) & " - " & gLibDatabaseNamePath )
' This will pop the last entry of the stack!
Call libLogErrorPopCallingPgm()
Print( gLibAdditionalErrorMessage )
End Function
HERE IS THE CODE FOR THE JAVASCRIPT FUNCTION
function jsLibGetGroupMembers( groupName:string, addressBook:NotesDatabase )
{
// This Function takes a passed in group name and gets all the members of that group.
// Not a big whoop until you consider nested group names. This is a recursive routine.
//
// Inputs : Name of the group to fetch the members of.
//
// Uses : Global objects
//
// Outputs : Returns an array of members
//
// History:
// 02.19.2001 - Steven Rieger : Created Function.
var groupView:NotesView;
var groupMainDoc:NotesDocument;
var groupMembers:java.util.Vector;
var nestedGroupMembers = new Array();
var arrayOfMembers = new Array();
var mainIndex:Integer;
var nestedIndex:Integer;
var resultIndex:Integer;
print( "Begin jsLibGetGroupMembers - Passed in Name: " + groupName );
groupView = addressBook.getView( "($VIMGroups)" )
if( groupView == null )
{
print( "group document not found!" );
return nestedGroupMembers;
}
// gLibAdditionalErrorMessage = "Fetching Group Main Document " & groupName
groupMainDoc = groupView.getDocumentByKey( groupName, true )
resultIndex = 0
// Did we find a matching group document?
if( groupMainDoc != null )
{ // is the group name already in the global list of groups?
if( !(groupName.toLowerCase() in gListOfGroupNames ) )
{
// Add the group name to the globla list of groups to prevent processing duplicate groups
gListOfGroupNames[ groupName.toLowerCase() ] = " "
groupMembers = groupMainDoc.getItemValue( "Members" );
for( groupMemberIndex = 0; groupMemberIndex < groupMembers.length; groupMemberIndex++ )
{
// Fetch any nested group members if the current member is a group name
nestedGroupMembers = jsLibGetGroupMembers( groupMembers[groupMemberIndex], addressBook );
if ( typeof nestedGroupMembers[0] === 'undefined' || nestedGroupMembers[0] === null )
{
// If no group was found and we have an actual member name add it to the list.
if( groupMembers[groupMemberIndex].length > 0 )
{
print( "adding user to array: " + groupMembers[groupMemberIndex] + " resultIndex = " + resultIndex );
arrayOfMembers[resultIndex] = groupMembers[groupMemberIndex];
resultIndex += 1;
}
else
{
print( "No User to Add!");
}
}
else
{
// If this was a nested group we found add the members of that group to the list
for( nestedGroupMemberIndex = 0; nestedGroupMemberIndex < nestedGroupMembers.length; nestedGroupMemberIndex++ )
{
print( "adding nested user to array: " + nestedGroupMembers[nestedGroupMemberIndex] + " resultIndex = " + resultIndex );
arrayOfMembers[ resultIndex ] = nestedGroupMembers[nestedGroupMemberIndex];
resultIndex += 1;
}
}
}
}
else
print( "Duplicate Group!");
}
else
{
print( "no group doc found!" );
}
print( "exiting jsLibGetGroupMembers: " + "\n" + arrayOfMembers );
return arrayOfMembers;
}
This answer will no doubt seem ironic given my recent blog post, but here's an SSJS implementation that will return a sorted list of all members of a group hierarchy:
var AtFunctions = (function() {
function getGroupNames (groupRecord, serverName) {
var result = new java.util.TreeSet();
if (groupRecord) {
for (var eachMember in groupRecord.getItemValue("Members")) {
var nestedGroupRecord = getGroupRecord(eachMember, serverName);
if (nestedGroupRecord) {
result.addAll(getGroupNames(nestedGroupRecord, serverName));
nestedGroupRecord.recycle();
} else {
result.add(eachMember);
}
}
}
return result;
}
function getGroupRecord (groupName, serverName) {
var result = null;
try {
serverName = (serverName || session.getServerName());
var NAB = session.getDatabase(serverName, "names.nsf");
var groupView = NAB.getView("($VIMGroups)");
result = groupView.getDocumentByKey(groupName, true);
} catch (e) {
print("Error getting group record: " + e.toString());
}
return result;
}
var API = {
expandNameList: function(groupName, serverName) {
var result = new java.util.TreeSet();
if (groupName) {
var groupRecord = getGroupRecord(groupName, serverName);
if (groupRecord) {
result.addAll(getGroupNames(groupRecord, serverName));
groupRecord.recycle();
}
}
return result;
}
};
return API;
})();
var #ExpandNameList = AtFunctions.expandNameList;
The variable alias at the end will allow you to treat this as a custom #Function, if desired, so you can call this one of two ways:
var groupMembers = #ExpandNameList("All Employees");
var groupMembers = AtFunctions.expandNameList("All Employees");
// in either syntax, you can optionally pass a server name as a second argument
NOTE: it's using the Java TreeSet class instead of JavaScript arrays, which has the following benefits:
It's automatically sorted. You might not want this, but for this
type of operation, it's often useful.
It automatically ignores duplicates, so you should only get one instance of each name even if the same member exists in multiple subgroups.
Syntactically, it's just so much easier to manipulate than an array.
Enjoy. :)