I have two arrays in Javascript: code and submittedCode. I am trying to compare the two arrays. Each of the arrays is 4 integers long, and each integer is a random value of 1 to 6. I also have two variables: red and white. When the two are compared, the red variable should be set to the number of similarities in the arrays that are the same number, same index. White should be set to the number of similarities in the array that are the same number, but different indexes. For example, if the code array is [1, 3, 6, 5] and submittedCode is [1, 6, 4, 5], then red would be set to 2, and white would be set to 1. This is the same logic as the game Mastermind if anyone has played that. Below is what I have tried, but it is not working as intended.
for(let i = 0; i < code.length; i++) {
if(code[i] == submittedCode[i])
{
code.splice(i, 1);
submittedCode.splice(i, 1);
red++;
//console.log(i);
}
}
console.log(code);
var saveLength = code.length;
code = code.filter(function(val) {
return submittedCode.indexOf(val) == -1;
});
white = saveLength - code.length;
console.log(red + ", " + white);
let arr=[1,3,1,2] //two array we operate on
let arr2=[4,4,1,2]
let red=0
let white=0
//we need to check the current length of remaining array
let currentLength=arr.length
for(let i=0; i<currentLength; i++){
if(arr[i]===arr2[i]){
arr.splice(i,1) //if same number same index, remove this item from array
arr2.splice(i,1)
currentLength-=1 //currentLength-1 because we reduced the array
i-=1 //i-1 because we'd skip the next element
red+=1 //update red
}
}
//we basically do the same thing but with white
//but in the second array we look for the first index of the current element and remove that
for(let i=0; i<arr.length; i++){
if(arr2.includes(arr[i])){
//1: I should've taken away the item from arr2 first
//2: arr2.splice(arr2.findIndex(f=>f===arr[i],1)) notice I messed up where I put the 1 at the end
arr2.splice(arr2.findIndex(f=>f===arr[i]),1)
arr.splice(i,1)
i-=1
white+=1
}
}
Now this might not be the most optimal solution, you can do this in one loop, but for visibility I created 2 for loops, in the first we check the 'red' elements, and we take those out
in the second loop we check if there are any 'white' elements, and we take those out.
Related
I'm running this for loop and modifying some values on the go. It logs the values changed correctly in each iteration, but it repeats the last iteration when writing to sheets.
const rngList = cadSheet.getRangeList(dataRng).getRanges();
//Gets the ranges' values and push them into an array;
let values = [];
for (let i = 0; i < rngList.length; i++) {
values = [].concat(values, rngList[i].getValues().flat());
//values.push([rngList[i].getValue()]);
}
let itens = [];
for (let a = 0; a < tamanhosEscArr.length; a++) {
for (let r = 0; r < coresEscArr.length; r++) {
values[4] = variacao++;//Increments an ID number
values.splice(29, 1); //removes this element
values.splice(29, 0, tamanhosEscArr[a]); //inserts size being iterated over
values.splice(30, 1);//removes this element
values.splice(30, 0, coresEscArr[r]); //inserts color being iterated over
Logger.log('Item: ' + values) //logs all 18 or so items, with their corresponding sizes and colors
itens.push(values);
}
}
suporteSheet.getRange(suporteSheet.getLastRow() + 1, 1, itens.length, itens[0].length).setValues(itens); //Writes the last iteration as many times as the iterations (18)
This is the log, showing the correct result:
This is how this is writing to the spreadsheet:
I can't see where the flaw is here, besides my existence.
Thanks for the light!
Try to change:
itens.push(values);
to:
itens.push(values.slice());
Đ•xplanation
Log shows you the current state of the array values at every iteration of the loop. During the next iteration, you change the array values. And all 'previous instances' of the array are changing as well. This is why you're getting the 18 identical arrays. Because all of them are 'references' to the same array values.
If you want to prevent the changes in the 'previous instances' you have to make a copy of current state of the array values and put in the itens this copy. The method array.slice() returns a copy of a given array.
I have a single 1d array storing a series of scores. My end goal is to have the 5 highest scores with brackets around them ( e.g. (score) ) for me to then format and output onto the display. In the case where there are duplicate scores, the first occurrences would be bracketed, up to that 5 top values.
So for example:
[9,8,10,9,6,8,6,5,4,4,3,3,6] would become [(9),(8),(10),(9),6,(8),6,5,4,4,8,3,8]
What I've tried so far is this:
var topvals = scores.sort((a,b) => b-a).slice(0,5);
for(var j=0; j< scores.length; j++){
if(topvals.length==0){
break;
}else if(topvals.includes(scores[j])){
scores[j] = "(" + scores[j] + ")";
topvals.splice(topvals.indexOf(scores[j]),1);
}
}
With the idea that topvals is an array containing the top 5 values, and I then loop through scores looking for those values, removing them each time.
What this results in is the first 5 values of scores having brackets around them.
I'm happy to go a completely different route with this, or just fix what I've done so far. Thanks in advance.
sort with indexes attached. Use index positions to change to desired format. O(N log N) for the sort.
scores = [9,8,10,9,6,8,6,5,4,4,3,3,6]
scores.map((n,i)=>({n,i})) // each object as n: number, i: index
.sort((a,b)=>a.n-b.n).slice(-5) // sort, slice top 5
.forEach(({i})=>scores[i]=`(${scores[i]})`) // add parens by indexes
console.log(scores)
If you have very, very large data sets and need something closer to O(N), you'll want to implement a pivot selecting algorithm. Just sorting is simpler.
The call to sort() sorts scores in place, which means it changes the scores array. So that is why you need to clone it first, then sort, then slice. Also you probably want to eliminate duplicates from your scores. I linked a stack overflow answer that describes how to do that. Since filter does not filter scores in place, but rather returns a new array, you don't need to explicitly call slice(0) to clone scores.
var scores = [9,8,10,9,6,8,6,5,4,4,3,3,6];
// Function from linked SO answer.
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// Filter unique scores into copy of array, then slice the top 5.
var topvals = scores.filter(onlyUnique).sort((a,b) => b-a).slice(0,5);
for (var j=0; j< scores.length; j++) {
if( topvals.length==0) {
break;
} else if(topvals.includes(scores[j])) {
scores[j] = "(" + scores[j] + ")";
topvals.splice(topvals.indexOf(scores[j]),1);
}
}
Get all unique values in a JavaScript array (remove duplicates)
I am working on an algorithm from leetcode.
here is the description:
Given an array and a value, remove all instances of that value in
place and return the new length. Do not allocate extra space for
another array, you must do this in place with constant memory. The
order of elements can be changed. It doesn't matter what you leave
beyond the new length. Example: Given input array nums = [3,2,2,3],
val = 3 Your function should return length = 2, with the first two
elements of nums being 2.
My question is based on the following code:
var removeElement = function(nums, val) {
var count = 0;
for(i=0; i<nums.length; i++){
if(nums[i] == val) {
nums.splice(i,1);
i--;
}
}
};
My question is, why does decrementing with i-- work but incrementing with i++ does not work?
A situation in which my answer is not accepted is when the input array is [3, 3], and the value is 3.
Splice removes the element at i from the array, so you need to stay at the current position, if you want to go on iterating normally. As theres an i++ in the for loop, it would normally go one position forward. So you need to go one step backward before to stay at the same position.
nums=[3,2,2,3]
val=3;
//first iteration
i=0
current=3//===val
nums.splice(0,1);//nums=[2,2,3]
i--;//i=-1
//next iteration
i++;//i=0
current=2;
//next iteration
i++;//i=1
current=2;
//next iteration
i++;//i=2
current=3;
nums.splice(2,1);//nums=[2,2]
i--;//i=1
//next iteration
i++;//i=2 === nums.length => break
In the case [3,2,2,3] it does not matter if you use i++ instead of i-- as it will jump over indexes 1 and 2 wich are not relevant. So this buggy code works by accident...
I have an array [1,1,1,0] (any size of), the minimum length of array and number 1 is 3. I want to keep moving the value of 1s 1 element up so it could move to [0,1,1,1], then back to [1,1,1,0].
My loop sort of work in recursive mode, but I'm not sure how to reset the values, so after 4 loops, my entire array is filled with 0's.
More lengthily array would traverse as so:
Example:
[1,1,1,0,0,0]-> [0,1,1,1,0,0]-> [0,0,1,1,1,0]-> [0,0,0,1,1,1]->
[1,1,0,0,0,1]-> [1,1,1,0,0,0]-> [0,1,1,1,0,0]-> [0,0,1,1,1,0]->
And so on for ever...
Code:
function flip(images, active) {
var new_active = active;
setTimeout(function() {
active.reverse();
active[active.length] = 0;
active.reverse();
active.pop();
for(var i = 0; i < active.length; i++) {
alert(active[i]);
}
flip(images, active);
}, 5000);
}
Depending on which direction you want to do, I would suggest using shift() and push(), or pop() and unshift().
Basically, shift() and unshift() add or remove an element from the front of the array, and push() and pop() add or remove an element from the back of the array.
For the example you have given, you'll probably want to pop() off the end of the array and unshift() to the front:
function rotateArray(arr) {
var element = arr.pop();
arr.unshift(element);
}
// Repeat in loop, timeout, etc. as necessary
First pop(store it).So [abcd]->[abc] and you have stored d.
Reverse. So [abc]->[cba].
Add the popped element. So [cba]->[cbad]
Reverse. So [cbad]->[dabc].
I hope you wanted that?
See this too.
Upvote if it helped you. :(
var arr = [1, 1, 1, 0, 0, 0],
startIndex = arr.indexOf(1),
sliceLength = 3,
slice;
while(arr[arr.length - 1] === 0) {
// slice out the 1's (modifies the original array)
slice = arr.splice(startIndex, sliceLength);
// splice the 1's back in, one spot over
arr.splice.apply(arr, [++startIndex, 0].concat(slice));
console.log(arr);
}
http://jsfiddle.net/sn7ujb90/1/
there are many questions/answers dealing with this topic. None match my specific case. Hopefully someone can help:
I have an array of indexes such as:
var indexes = [24, 48, 32, 7, 11];
And an array of objects that look similar to this:
var items = [{
name : "whatever",
selected : false,
loading : true,
progress : 55,
complete : false
},
{
name : "whatever 2",
selected : false,
loading : false,
progress : 100,
complete : true
}];
Each integer within the indexes array corresponds to the actual index of an object within the items array.
Lastly I have a variable which defines the new insert position within the items array:
var insertindex = ??
What I would like to do is to take all objects in the items array that have the indexes stored in the indexes array, remove them, then finally place them back, all next to each other at a specified index defined by the variable insertindex.
I have been trying to use splice() by copying the objects at each index to a temporary array, then removing them from the original array, then finally looping through this new temporary array and putting them back into the original items array at the new positions, but seems to be hitting a mental brick wall and cannot get it to work correctly.
To summarize, I simply want to take all objects from the items array that match an index defined in the indexes array, put them together and reinsert them at a predefined index, back into the items array.
To help with conceptual visualization. If you think of the app as a javascript file manager, allowing the reordering of multiple file selections which do not have to be adjacent. The indexes array defining the current selection and the items array defining the list of files. And finally the rearoderindex defines the new insert position that all selected files should move to.
EDIT: As was rightly suggested here is the code I am playing with right now:
function reorder(items, indexes, insertindex){
var offset = 0;
var itemscopy = items.slice(0); //make shallow copy of original array
var temparray = new Array(); // create temporary array to hold pulled out objects
//loop through selected indexes and copy each into temp array
for(var i=0, len=indexes.length; i<len; i++){
array[i] = itemscopy[self.cache.selecteditems[i]];
}
//remove all selected items from items array
for(var i=0, len=indexes.length; i<len; i++){
items.splice(indexes[i], 1);
}
//finally loop through new temp array and insert the items back into the items array at the specified index, increasing the index each iteration using the offset variable.
for(var i=0, len=temparray.length; i<len; i++){
items.splice((insertindex+offset), 0, array[i]);
offset++;
}
}
I'm aware this is pretty horrible and that looping three times should not be necessary. But I've been trying lots of different methods, some working when reordering in one direction, some in the other an mostly, not at all. I figured I would look to optimize the function later, once I have it working with accuracy.
I'm certain I must be doing something extremely stupid or completely overlooking something, but for the life of me I can't work out what right now.
If you don't care about order of indexes array, I'd suggest another short solution:
items.splice.apply(items, [insertIndex, 0].concat(indexes.sort(function(a, b) {
return a - b;
})).map(function(i, p) {
return p > 1 ? items.splice(i - p + 2, 1).pop() : i;
}));
DEMO: http://jsfiddle.net/T83fB/
To make it short I used Array.map() method, which is not supported by old IE browsers. However it is always easy to use a shim from MDN.
You can use the .splice() function to add elements to an array, as well as removing items from it. The general principle is:
Sort indexes into ascending numeric order
Iterate over indexes, removing the element at that index (adjusting for the number of removed items) and storing it in a removedItems array
Add the removedItems array back in at the required index
The code to do that would look something like this:
var removedItems = [];
// sort indexes
indexes.sort(function(a, b) {
if(a < b) return -1;
else if(b < a) return 1;
return 0;
});
for(var i = 0; i < indexes.length; i++) {
var index = indexes[i];
removedItems.push(items.splice(index - removedItems.length, 1));
}
var insertIndex = 1;
items.splice.apply(items, [insertIndex, 0].concat(removedItems));
Take a look at this jsFiddle demo.