loop through 'distinct' values and ignore duplicates - javascript - javascript

I'm completely rewriting this question to explain it better,
i have a list of objects as shown in the image.
These all have the property statusCode: 62467 but the journey property goes like: 0,1,2,3,3,4,4,4,4
i want to loop through these objects and return the FIRST of the duplicated objects with the same journey number.
So i want to return the bold objects: 0,1,2,3,3,4,4,4,4
$.each(points, function (index, point) {
for (i = 0; i < journeyNumber.length; i++) {
if (point.k.journey === journeyNumber[i] && point.k.statusCode === '62467') {
console.log(point);
latlngs.push(point.j.aa.k);
latlngs.push(point.j.aa.B);
}
}
});
the screenshot is the log of console.log(point), so ideally i would like another loop inside which returns only the first object of the same journey number.
hope this makes sense and thank you for your time.

You can track which numbers have already been dealt with, and, on finding duplicates of them, skip them.
var already_seen = []; //container for logging unique values
$.each(points, function(index, point) {
if (already_seen.indexOf(point) !== -1) return; //if already in container, skip
already_seen.push(point); //log unseen values in the container
for (i = 0; i < journeyNumber.length; i++) {
if (journey === journeyNumber[i] && statusCode === '62467') {
latlngs.push(lat);
latlngs.push(lng);
console.log(journey)
}
}
});

How about making use of filter
var unique = [];
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
$.each(points, function(index, point) {
for (i = 0; i < journeyNumber.length; i++) {
if (journey === journeyNumber[i] && statusCode === '62467') {
latlngs.push(lat);
latlngs.push(lng);
unique.push(journey)
}
}
console.log(unique.filter(onlyUnique));
});

Related

How do I loop over an array at a given key on an object?

I was given the assignment to create a function that, given an object and a key, returns an array containing all the elements of the array located at the given key that are less than 100. I came up with this:
function getElementsLessThan100AtProperty(obj, key) {
var lessThan100 = [];
var targetedKey = obj[key];
if (targetedKey === undefined) {
return [];
}
for (i = 0; i < targetedKey.length; i++) {
if (targetedKey[i] < 100) {
lessThan100.push(targetedKey[i]);
}
}
return lessThan100;
}
Now this works, but I am wondering why my original code didn't. I tried to loop over the array at the given property by writing the code below, but it didn't work. Why can't i do this? Also, would someone show me how to clean up this code to make it shorter?
for (i = 0; i <obj[key].length; i++) {
if (obj[key[i]].length < 100) {
lessThan100.push(obj[key[i]]);
}
Because obj[key[i]] has to be obj[key][i], additionally you check if the length is smaller 100 which is probably not your intention.
The whole code could be written as:
const getLessThanHundred = (obj, key) =>
obj[key].filter(it => it < 100);
In your revised code you are checking if the length of the item in the array is less than 100, not if the value of the item is less than 100. You should be checking the value (ie < 100; not .length < 100)

Find duplicates in array JavaScript

So I'm working on a simple JavaScript web-based game. The goal is to guess a X digit random number. This means the random number can be 4, 5 digits up to whatever you want. You can actually play the game at www.juegodescifralo.com , (it's in Spanish, sorry about that).
The user inputs a number that is stored as an array. The random number is also generated as an array. Individual numbers in both arrays can be repeated.
There are three types of possible "values/numbers": the "good" ones are the numbers you chose that are in the same position as the ones in the random array. So for example:
Random array is: 1457
User input is: 6851
Number 5 is a "good" number, since it's in the same position. Then there are the second type of "values", which are "regular". This means they are inside the random number but not in the same position. In this example, number 1 would be a "regular" value. And the third type is the "bad" ones, which are not even inside the random array.
The function I've developed is as follows:
function checkNumbers(randomArray, myArray, good, regular, bad) {
for (var x = 0; x < randomArray.length; x++) {
var posRepetido = randomArray.indexOf(myArray[x]); //Is current number inside random array?
if (posRepetido == -1) { //It's not inside
console.log("number " + myArray[x] + "is not inside");
bad++;
} else { //It's inside
regular++;
if (myArray[x] == randomArray[x]) { //If it's the same number...
console.log("number " + myArray[x] + "is in the correct position");
good++;
regular--;
} else { //If it's not the same number
if (randomArray[posRepetido] != myArray[posRepetido]) {
console.log("number " + myArray[x] + "is inside but not in the same position");
} else {
console.log("number " + myArray[x] + "is not inside");
}
}
}
}
var obj = { //Return object for accessing later, to show feedback to the user.
good: good,
regular: regular,
bad: bad
};
return obj;
}
The code is a bit buggy. When there are duplicates in the random array, and one of them is marked as good, then the other one (even if it exists in user input) will be set as bad, not as regular as it should.
The thing becomes even more complicated since you should be able to play against any amount of digits. So I should be able to guess a 20 digit number without "problems".
You can play by yourself at www.juegodescifralo.com
How can I go about this? Any ideas how can I access array data more easily? Thank you very much!
Rather than indexOf comparisons against -1 and checks of myArray[x], it would probably be a lot easier to use includes and array methods such as forEach for better abstraction. All you really need is an if, an else if, and an else. For example:
function checkNumbers(randomArray, userArray, good=0, regular=0, bad=0) {
userArray.forEach((guess, i) => {
if (guess === randomArray[i]) good++;
else if (randomArray.includes(guess)) regular++;
else bad++;
});
return { good, regular, bad };
}
// 4 good
console.log(checkNumbers(
'1234'.split(''),
'1234'.split(''),
));
// 4 good, 2 bad
console.log(checkNumbers(
'1234'.split(''),
'123456'.split(''),
));
// 4 good, 2 regular
console.log(checkNumbers(
'1234'.split(''),
'123412'.split(''),
));
// all regular:
console.log(checkNumbers(
'123456789123456789'.split(''),
'912345678912345678'.split(''),
));
i think it is easier to loop thru it twice like this
function checkNumbers(randomArray, guessArray) {
var clone = randomArray.slice(0);
var good = 0;
var regular = 0;
var bad = 0;
var visited = [];
guessArray.forEach(function(guess, index) {
if (guess === clone[index]) { // the guess is in right position
good++;
clone[index] = "x"; // strike it out so it cannot be used later
visited.push(index);
} else if (clone.indexOf(guess) === -1) {
bad++;
visited.push(index);
}
});
guessArray.forEach(function(guess, index) {
if (!visited.includes(index)) {
var match = clone.indexOf(guess);
if (match !== -1) {
regular++;
clone[match] = "x"; // strike it out so it cannot be used later
}
}
});
return {
good: good,
bad: bad,
regular: regular
}
}
first loop is to check the good and bad. and strikeout the value it is good so it cannot be used again.
second loop to check for the regular and strikeout the value it is used so it cannot be used again.
This should work.
function guessNumber (numUser, numRandom) {
if (typeof numUser == 'number') {
numUser = numUser.toString().split('');
}
if (typeof numRandom == 'number') {
numRandom = numRandom.toString().split('');
}
if (typeof numRandom != 'object' || typeof numUser != 'object') {
return false;
}
if (numRandom == numUser) {
return true;
}
var numRegular = {},
numBuenos = {},
numMalos = {},
numRepeat = {};
for(var i = 0; i < numRandom.length; i++) {
if (!numRepeat[numRandom[i]]) {
numRepeat[numRandom[i]] = 0;
}
numRegular[numRandom[i]] = 0;
numRepeat[numRandom[i]]++;
}
for (var i = 0; i < numUser.length; i++) {
if (numUser[i] == numRandom[i]) {
numBuenos[numUser[i]] = numUser[i];
}else if ($.inArray(numUser[i], numRandom)) {
if (!numRegular[numUser[i]]) {
numRegular[numUser[i]] = 0;
}
if (numRegular[numUser[i]] < numRepeat[numUser[i]]) {
numRegular[numUser[i]]++;
} else {
numMalos[numUser[i]] = numUser[i];
}
} else {
numMalos[numUser[i]] = numUser[i];
}
}
return {
regular: Object.values(numRegular).reduce((a, b) => a + b),
buenos: Object.keys(numBuenos).length,
malos: Object.keys(numMalos).length
};
}
console.log(guessNumber(8365, 8512));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Eliminate duplicate values javascript

I try to draw a graph from tens of thousands points, but because this number is so big i need to reduce it. Many of them have duplicates. I tried to reduce the number using this:
var array=_.reject(data,function(object,i){
return i>0 && (data[i-1].a === object.a && data[i-1].b===object.b && data[i-1].c===object.c);
});
How can i modify this function, or to create a new one, in order to keep first and last value considered duplicate. Those are different by another attribute 'd' which represent a time stamp.
//return filtered points, compareFunction for sorting, equalFunction for
//removing points
function removeDuplicate(data,compareFunction,equalFunction) {
data.sort(function(pointa, pointb) {
var compare = compareFunction(pointa,pointb);
return compare;
});
var arr = new Array();
var prev = new Object();
var index = 0;
for (var i = 0; i < data.length; i++) {
if (i == 0 || !(equalFunction(prev,data[i]))) {
arr[index++] = data[i];
prev = data[i];
}
}
return arr;
}
function compareFunction(pointa,pointb){
return (pointa.a + pointa.b + pointa.c) - (pointb.a + pointb.b + pointb.c);
}
function equalFunction(pointa,pointb){
return pointa.a == pointb.a && pointa.b == pointb.b && pointa.c == pointb.c;
}
example - https://jsfiddle.net/8xu4Lwp2/
The simplest way to eliminate duplicates from an array in JavaScript is to cast it as a Set and then back to an Array. Sets don't store duplicates.
// not sure why setArr isn't logging, it does in Opera console.
arr=[1,1,2,2,3,3];
console.log(arr);
setArr=new Set(arr);
console.log(setArr);
newArr=[...setArr];
console.log(newArr);
Cool solution:
var unique = Array.from(new Set(arrayWithDuplicatedValue));

Find how many times "Index" appers in array

I'm trying to find out if "Index" exist in my array, and second then count how many time it does appear.
Nothing of what I'm trying is working, this is the best attempt i've made, but cant turn my head around this.
var arr = {"__metadata":{"id":"a5e55ca2-c574-434e-8ec3-1b9cd4595bcb","uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)","etag":"\"2\"","type":"SP.Data.SalesListItem"},"FirstUniqueAncestorSecurableObject":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/FirstUniqueAncestorSecurableObject"}},"RoleAssignments":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/RoleAssignments"}},"Activities":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/Activities"}},"AttachmentFiles":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/AttachmentFiles"}},"ContentType":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/ContentType"}},"GetDlpPolicyTip":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/GetDlpPolicyTip"}},"FieldValuesAsHtml":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/FieldValuesAsHtml"}},"FieldValuesAsText":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/FieldValuesAsText"}},"FieldValuesForEdit":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/FieldValuesForEdit"}},"File":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/File"}},"Folder":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/Folder"}},"ParentList":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/ParentList"}},"Properties":{"__deferred":{"uri":"https://lavanet.sharepoint.com/sites/devcla/_api/Web/Lists(guid'cc4de542-1c06-4f53-b787-b8a2d42fe21e')/Items(1)/Properties"}},"FileSystemObjectType":0,"Id":1,"ServerRedirectedEmbedUri":null,"ServerRedirectedEmbedUrl":"","ContentTypeId":"0x010048CF0CAB992F7B409B79C034586FFB7E","Title":"Test data 1","Date":"2017-01-01T08:00:00Z","Index":20,"Index2":15,"ID":1,"Modified":"2017-04-18T12:27:19Z","Created":"2017-02-03T10:02:10Z","AuthorId":17,"EditorId":17,"OData__UIVersionString":"1.0","Attachments":false,"GUID":"d87fa9d2-c81e-4dfd-b568-c8a300fc12d8"}
function containsObject(obj, list) {
var x;
for (x in list) {
if (list.hasOwnProperty(x) && list[x] === obj) {
return true;
}
}
return false;
}
console.log(containsObject("index", arr));
Would love if someone could help a bit
If you would like to count both if key and/or value of prop === index and not bother of case-sensitivity, then you can try something like this.
function containsObject(obj, list) {
var cnt = 0;
for (var x in list) {
var val = list.hasOwnProperty(x) && list[x] ? list[x].toString() : '';
if (x.toLowerCase() === obj.toLowerCase() ||
val.toLowerCase() === obj.toLowerCase()) {
cnt++;
}
}
return cnt;
}

Recursion without overun

I've been looking for real world examples of recursion. Remember, programming Wizards, I'm and artist and in Photoshop scripting (scriptus modus operandi) it's normally used to loop over all layers and sub layers.
I'm working on a (simple) recursion script to solve a four digit combination lock. You know, start with 1, then try 2, then 3 etc until the solution is found. To make things easy in the example the second digit is correct so we know that we don't have to change that. Also the initial state the numbers start zero, but we know there are no zeroes in the final solution.
The attempt must match the solution AND also add up to 10 in order to
be solved.
This may seem a bit stoppid, but I want to put in a two part condition of the solution, mainly because I can then apply what I've learned and write a brute force suduko solver. But you must crawl before you can ice skate...
var puzzle = [0,2,0,0]; // source
var solution = [1,2,3,4];
var s = superCopy(puzzle); // working array
drawPuzzle(s);
solvePuzzle(s, puzzle);
var total = checkTotal(s, solution);
var solution = checkSolution(s, solution);
function checkTotal(arr, source)
{
var c = 0;
// count the total
for (var i = 0; i < arr.length; i++)
{
c += arr[i];
}
if (c == 10)
{
alert("Total OK")
return true;
}
}
function checkSolution(arr, source)
{
// check the solution
for (var i in arr)
{
if (arr[i] != source[i]) return false
return true;
}
}
function solvePuzzle(arr, source)
{
for (var i = 0; i < arr.length; i++)
{
// check the source
var sourceCell = source[i];
//alert("checking source " + sourceCell)
//if it's a zero we can change it
if (arr[i] == 0)
{
cell = arr[i];
cell+=1;
if (cell > 4) cell = 0;
arr[i] = cell;
}
}
// check the solution
for (var i in arr)
{
// overflow time!
if (arr[i] != source[i]) solvePuzzle(arr, source)
else
{
alert("All done!")
}
}
}
function drawPuzzle(arr)
{
var p = "";
var c = 0;
for (var i = 0; i < arr.length; i++)
{
if (arr[i] == 0) p += "-"
else p += arr[i];
c+=1;
}
alert(p);
}
function superCopy(arr)
{
// returns a true copy of an array
tempArr = new Array();
for (var i = 0; i < arr.length; i++)
{
if (arr[i] == 0) tempArr[i] = 1 // changed, thanks Nostradamnit!
else tempArr[i] = arr[i]
}
return tempArr
}
The script is incomplete. This what I have so far, it falls over with an overflow error. Note solvePuzzle and checkTotal functions are not called because I realised that solvePuzzle needs to call itself and work out the solution...which is when I ran into overflow problems and got a bit confused.
I realise that this type of question runs dangerously close to a "fix my code" venture, so I'm prepared to put a bounty out for it. Thanks.
There are a couple of problems with your code. First up, your checkSolution function stops at the very first number that matches. You probably want it to check every number before returning true, so you should move return true outside the for loop. It only gets there if all numbers match up.
Another flaw is the superCopy function, which as Nostradamnit pointed out has a flawed condition.
Your next problem is in solvePuzzle, where you have this:
if (arr[i] == 0)
{
cell = arr[i];
cell+=1;
if (cell > 4) cell = 0;
arr[i] = cell;
}
The thing is, because arr[i] is 0 and you only add 1, cell will never be 4. So your if is never going to fire. This is where your infinite loop is: it only increments values that are zero with one, so after all zeros became one, it never goes further and you keep checking if "1111" is the solution.
Now the overflow: you shouldn't be calling solvePuzzle for every cell, this grows exponentially:
for (var i in arr)
{
// overflow time!
if (arr[i] != source[i]) solvePuzzle(arr, source)
else
{
alert("All done!")
}
}
Also, you never check the result again, so the looping never ends. You would probably want to change this to this:
if(checkTotal(arr) && checkSolution(arr, source))
{
alert("All done!");
return;
}
solvePuzzle(arr, source);
As a side note (not a bug causing thing): your checkTotal function isn't using the source parameter, so you can probably leave that out. Also, there is a rogue variable called cell in solvePuzzle, which isn't a big deal in this case, but it would be better to put var in front of it so it doesn't become global. Also, there is a sourceCell variable that never gets used.
At first glance, it seems that your superCopy function is flawed. You create an empty array, then compare its 0 index (which doesn't exist) to the input array. Is that where you are getting your "overflow"?
The problem seems to be that you call solvePuzzle(arr, source) multiple times in the same iteration:
for (var i in arr)
{
// overflow time!
if (arr[i] != source[i]) solvePuzzle(arr, source)
else
{
alert("All done!")
}
}
So you iterate over every item in the array, and if it is not equal to the source item, you call solvePuzzle again. But if you have several items that don't match, solvePuzzle will get called multiple times on the same array. And for each call, it gets called again multiple times. Therefore your function calls grow exponentially and result finally in a stack overflow.
What you probably intended to do, is the following:
var areArraysEqual = true;
for (var i in arr)
{
if (arr[i] != source[i]) {
areArraysEqual = false;
break;
}
}
if (areArraysEqual) {
alert("All done!");
} else {
solvePuzzle(arr, source);
}
I haven't looked over your solution yet, but i did write a recursive one for myself to solve the problem. Perhaps it can be of help as a guideline?
var solution = [1,2,3,4];
function checkSolution(arr) {
return solution.every(function(item, index){ return item === arr[index]; });
}
function increment(arr) {
for (var i=0; arr[i] === 9; i++) {
arr[i] = 0;
}
arr[i]++;
return arr;
}
function solvePuzzle(arr) {
if (isNaN(arr[arr.length-1])) {
return null;
}
if (checkSolution(arr)) {
return arr;
}
return solvePuzzle(increment(arr));
}
var solution = solvePuzzle([1,1,1,1]);
console.log(solution); // [1,2,3,4]
Maybe little bit off topic but I have created the easiest recursion example possible in my opinion.
http://jsfiddle.net/33yfS/
var str = "9785";
function rec(a, b)
{
var c=0;
if(b==-1)
return "";
if(a!=str.charAt(b))
return rec(a+1, b);
else
{
return rec(0,b-1)+""+a;
}
}
var ans = rec(0,str.length-1)

Categories

Resources