Does a value exist in an Array not working? - javascript

So, I have this function it takes two arrays of objects, workArr and arr, and match there id property and then add up the hours property to store in the workArr array.
var workArr = [];
var arr = [];
foundID = [];
function blah()
{
var i = 0;
var j = 0;
//Add up the hours
for( i=0; i < workArr.length ; i++)
{
for( j=0; j < arr.length ; j++)
{
//Makesure the id's match and the week is within the given time frame
//ALSO make sure the id hasn't already be visited
if( cond1 && !(isInArray(workArr[i].id)))
{
workArr[j].total = workArr[j].total + arr[j].hrs;
foundId.push(workArr[j].id);
}//end if id === id
}//end for j loop
}//end for i loop
printArr(foundId);
}//End blah()
//Checks if the given id has already be found
//returns true or false
function isInArray(id) {
return foundID.indexOf(id) > -1;
}
The problem is when I print out my already visited id array, once this function ends, there are duplicates in it, and there shouldn't be because if a duplicate is found it breaks the if condition and doesn't get added to the already found id's. So somehow my if condition isn't weeding out the already visited id's. Please help me solve this seemingly easy problem.

Solved with the help from the comments should be workArr[i] not workArr[j]
if( cond1 && !(isInArray(workArr[i].id)))
{
workArr[i].total = workArr[i].total + arr[j].hrs; // workArr[i]
foundId.push(workArr[i].id); // workArr[i]
}//end if id === id

Related

Remove duplicate values from flat ARRAY

I'm wanting to remove duplicate values from the array tabData produced by the script below.
I've found numerous posts here that mention "removing duplicates from array", but don't seem to be relevant to my exact goal.
I've tried filter, I've tried using this answer and adjusting the variables to fit my script, but it did not remove the duplicates.
Surely there is a simple function that does exactly what I'm looking for, I'm just not finding it.
function getTabArray() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var version = ss.getRangeByName("version").getValue().toString();
var updateTabsName = "updateTabs";
var updateTabsSheet = ss.getSheetByName(updateTabsName);
var tabDataRows = updateTabsSheet.getLastRow();
var tabDataCols = updateTabsSheet.getMaxColumns() - 1;
var tabDataRange = updateTabsSheet.getRange(1, 2, tabDataRows, tabDataCols);
var tabData = tabDataRange.getValues(); // <-- REMOVE DUPLICATES
for (var i = 0; i < tabData.length; i++) {
if (tabData[0][i] != "" && tabData[0][i] > version) {
for (var j = 0; j < tabData.length; j++) {
if (tabData[j][i] != "" && j > 0) {
Logger.log("tabData[j][i] = " + tabData[j][i]); // tabData[j][i] = all values in column
}
}
}
}
}
This is the array it currently produces:
2.20200514.2,2.20200514.0,2.20200513.2,2.20200513.1,2.20200513.0,2.20200512.0,1.20200405.1,,tabDefinitions,Sheet6,Sheet6,changeLog,Sheet6,Index,,,,Sheet7,,Sheet7,settings,,,,Sheet8,,Sheet8,tabDefinitions,,,,,,,changeLog,,,,,,,updateTabs
I want to remove all duplicates (Sheet6, Sheet7, Sheet8, etc.) from the array.
EDIT:
After one more search, I found this answer which contains exactly what was answered below, but when I use any method in that answer, I still get all duplicates. Not sure what I'm doing wrong or not doing right.
var unique = tabData.filter((v, i, a) => a.indexOf(v) === i);
EDIT 2:
I realized my array was not actually "flat", so I added var tabData = tabDataRange.getValues().flat(); and now everything works!
You can use ES6 Set() function to remove the duplicates
const newArray = [...new Set(arrayWithDuplicates)];

Check for duplicates in array with randomly generated values

I'm working on exercism question and am stuck on one of the jasmine-node based tests, which says that I should be able to generate 10000 random names without any clashes (e.g. 2 randomly generated names match). This is the test:
it('there can be lots of robots with different names each', function() {
var i,
numRobots = 10000,
usedNames = {};
for (i = 0; i < numRobots; i++) {
var newRobot = new Robot();
usedNames[newRobot.name] = true;
}
expect(Object.keys(usedNames).length).toEqual(numRobots);
});
What I think I need to do is:
Create an array to hold all the names (robotNames),
Each time a name is generated, check if it exists in the array,
If it does, generate another name,
If it doesn't, add it to the array.
And here is my code so far...
"use strict";
var robotNames = [];
var name;
var Robot = function() {
this.name = this.generateName();
};
Robot.prototype.generateName = function() {
var letters = "";
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var numbers = "";
var digits = "0123456789";
// generate random characters for robot name...
for( var i=0; i < 2; i++ ) {
letters += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
};
for( var i=0; i < 3; i++ ) {
numbers += digits.charAt(Math.floor(Math.random() * digits.length));
};
name = letters+numbers;
// Loop through array to check for duplicates
for(var i = 0; i < robotNames.length; i++) {
if (name == robotNames[i]) {
this.generateName();
return;
} else {
robotNames.push(name);
}
}
return name;
};
Robot.prototype.reset = function() {
this.name = this.generateName();
};
module.exports = Robot;
The test fails with an error message: "Expected 9924 to equal 10000."
The '9924' number is slightly different each time I run the test. I'm thinking this means the generateName function is eventually generating 2 matching random names. It seems as though my loop for checking duplicates is not being run and I'm not sure why.
I have tried a couple of different versions of the loop but with no success. So my questions is a) is my approach correct and there is something wrong with the syntax of my loop? or b) have I got the wrong idea about how to check for duplicates here?
Any pointers appreciated, thanks.
The problem is in this bit:
for(var i = 0; i < robotNames.length; i++) {
if (name == robotNames[i]) {
this.generateName();
return;
} else {
robotNames.push(name);
}
}
...you probably only want to push your name if NONE of the names fail to match. Here you're adding it to the list as soon as you find ONE that doesn't match. You want something more like:
for(var i = 0; i < robotNames.length; i++) {
if (name == robotNames[i]) {
return this.generateName();
}
}
robotNames.push(name);
(actually, combined with the fact that you weren't even returning the recursive call to this.generateName(), I'm not sure how your program could work...)
Find a library with an implementation for Sets. Collections.js is a good example.
One property of a set is that it doesn't have duplicates. So when you add a value to a set it will look for a duplicate and then add the value if no duplicate exists.

How to find the count of images that have same file name?

Can you please help me how to find the no.of images for same file name,
var images =["Cat.png", "Cock.png","Dog.png","Parrot.png","Penguin.png",
"Rabbit.png","Parrot.png"];
here I have 7 images in the array...
I need count like..
Cat:1
Parrot :2
Penguin:1
Please give me the suggestion
Thanks,
Rajasekhar
The usual solution is to use an object as a map to make the link between the keys (name of the files) and the count :
var count = {};
for (var i=images.length; i-->0;) {
var key = images[i].split(".")[0]; // this makes 'Parrot' from 'Parrot.png'
if (count[key]) count[key]++;
else count[key] = 1;
}
Then you have, for example count['Parrot'] == 2
Demonstration : http://jsfiddle.net/tS6gY/
If you do console.log(count), you'll see this on the console (Ctrl+Uppercase+i on most browsers) :
EDIT about the i--> as requested in comment :
for (var i=images.length; i-->0;) {
does about the same thing than
for (var i=0; i<images.length; i++) {
but in the other directions and calling only one time the length of the array (thus being very slightly faster, not in a noticeable way in this case).
This constructs is often used when you have a length of iteration that is long to compute and you want to do it only once.
About the meaning of i--, read this.
i-->0 can be read as :
decrements i
checks that the value of i before decrement is strictly positive (so i used in the loop is positive or zero)
Not sure about efficiency, but this should do:
var images =["Cat.png", "Cock.png","Dog.png","Parrot.png","Penguin.png","Rabbit.png","Parrot.png"];
images.forEach(function(img){
var count = 0;
images.forEach(function(image, i){
if(img === image){
delete images[i];
count++;
}
});
console.log(img, count);
});
DEMO
You can keep unique keys in an array and use another array for counting the frequency:
var images =["Cat.png", "Cock.png","Dog.png","Parrot.png","Penguin.png","Rabbit.png","Parrot.png"];
var counts = [];
var keys = [];
for (i = 0; i < images.length; i++){
if (!counts[images[i]]) {
counts[images[i]] = 0;
keys.push(images[i]);
}
counts[images[i]]++;
}
for (i = 0; i < keys.length; i++) alert(keys[i] + " : " + counts[keys[i]]);
​
Here is a demo : http://jsfiddle.net/e5zFC/1/

How to count the array from specific JSON object value?

here is my javascript:
var json = '{"GetReportIdResult":[{"bulan":"4","total":"1728","type":"CHEESE1K","uang":"8796383"},{"bulan":"4","total":"572476","type":"ESL","uang":"5863408410"},{"bulan":"4","total":"33507","type":"WHP","uang":"235653242"},{"bulan":"5","total":"4761","type":"CHEESE1K","uang":"134877865"},{"bulan":"5","total":"245867","type":"UHT","uang":"1446787280"},{"bulan":"5","total":"47974","type":"WHP","uang":"631929807"},{"bulan":"6","total":"5762","type":"CHEESE1K","uang":"293393832"},{"bulan":"6","total":"236803","type":"UHT","uang":"2219506085"},{"bulan":"6","total":"24853","type":"WHP","uang":"386175022"}]}';
obj = JSON.parse(json);
var arrayobj = obj.GetReportIdResult.length;
alert (arrayobj);
I want to count how many type in the same bulan value, (e.g. there are 3 type = CHEESE1K, UHT, and ESL in bulan = 4)
how to do that?
There's still a typo in your JSON: you've got two commas in a row between the first two "bulan":"6" objects. But assuming you fix that...
If you're asking how to count distinct types for a particular bulan value you can do something like this:
function countTypesForBulan(resultArray, bulanVal) {
var i,
types,
count = 0;
for (i=0, types = {}; i < resultArray.length; i++)
if (resultArray[i].bulan === bulanVal && !types[resultArray[i].type]) {
types[resultArray[i].type] = true;
count++;
}
return count;
}
console.log( countTypesForBulan(obj.GetReportIdResult, "4") ); // logs 3
The above loops through the array looking for a particular bulan value, and when it finds one it checks if it has already seen the associated type - if not, it adds it to the types object and increments the counter.
Demo: http://jsfiddle.net/pAWrT/
First of all, put the JSON into a string,
else your example code wont work.
var json = '{"GetReportIdResult":[{"bulan":"4","total":"1728","type":"CHEESE1K","uang":"8796383"},{"bulan":"4","total":"572476","type":"ESL","uang":"5863408410"},{"bulan":"4","total":"33507","type":"WHP","uang":"235653242"},{"bulan":"5","total":"4761","type":"CHEESE1K","uang":"134877865"},{"bulan":"5","total":"245867","type":"UHT","uang":"1446787280"},{"bulan":"5","total":"47974","type":"WHP","uang":"631929807"},{"bulan":"6","total":"5762","type":"CHEESE1K","uang":"293393832"},,{"bulan":"6","total":"236803","type":"UHT","uang":"2219506085"},{"bulan":"6","total":"24853","type":"WHP","uang":"386175022"}]}';
Then,
Iterate with for and count in a variable or a hashmap.
Since GetReportIdResult is an array, you can:
for( var i : obj.GetReportIdResult ){
obj.GetReportIdResult[i] ... // Use at will.
This will give you a map object which will contain the count for each bulan value. For example, map['4'].count will return 3.
var i, row, arr = obj.GetReportIdResult, map = {};
for (i = 0; i < arr.length; i++) {
row = arr[i];
map[row.bulan] = map[row.bulan] || {count: 0};
if (map[row.bulan][row.type] === undefined) {
map[row.bulan][row.type] = row.type;
map[row.bulan]['count'] += 1;
}
}
console.log (JSON.stringify(map));​
JSFiddle here.

Finding an object and returning it based on search criteria

I have been searching online all day and I cant seem to find my answer. (and I know that there must be a way to do this in javascript).
Basically, I want to be able to search through an array of objects and return the object that has the information I need.
Example:
Each time someone connects to a server:
var new_client = new client_connection_info(client_connect.id, client_connect.remoteAddress, 1);
function client_connection_info ( socket_id, ip_address, client_status) {
this.socket_id=socket_id;
this.ip_address=ip_address;
this.client_status=client_status; // 0 = offline 1 = online
};
Now, I want to be able to search for "client_connection.id" or "ip_address", and bring up that object and be able to use it. Example:
var results = SomeFunction(ip_address, object_to_search);
print_to_screen(results.socket_id);
I am new to javascript, and this would help me dearly!
Sounds like you simply want a selector method, assuming I understood your problem correctly:
function where(array, predicate)
{
var matches = [];
for(var j = 0; j < array.length; j++)
if(predicate(j))
matches.push(j);
return matches;
}
Then you could simply call it like so:
var sample = [];
for(var j = 0; j < 10; j++)
sample.push(j);
var evenNumbers = where(sample, function(elem)
{
return elem % 2 == 0;
});
If you wanted to find a specific item:
var specificguy = 6;
var sixNumber = where(sample, function(elem)
{
return elem == specificguy;
});
What have you tried? Have you looked into converting the data from JSON and looking it up as you would in a dictionary? (in case you don't know, that would look like object['ip_address'])
jQuery has a function for this jQuery.parseJSON(object).
You're going to need to loop through your array, and stop when you find the object you want.
var arr = [new_client, new_client2, new_client3]; // array of objects
var found; // variable to store the found object
var search = '127.0.0.1'; // what we are looking for
for(var i = 0, len = arr.length; i < len; i++){ // loop through array
var x = arr[i]; // get current object
if(x.ip_address === search){ // does this object contain what we want?
found = x; // store the object
break; // stop looping, we've found it
}
}

Categories