Find the first repeated number in a Javascript array - javascript

I need to find first two numbers and show index like:
var arrWithNumbers = [2,5,5,2,3,5,1,2,4];
so the first repeated number is 2 so the variable firstIndex should have value 0. I must use for loop.
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
var firstIndex
for (i = numbers[0]; i <= numbers.length; i++) {
firstIndex = numbers[0]
if (numbers[i] == firstIndex) {
console.log(firstIndex);
break;
}
}

You can use Array#indexOf method with the fromIndex argument.
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
// iterate upto the element just before the last
for (var i = 0; i < numbers.length - 1; i++) {
// check the index of next element
if (numbers.indexOf(numbers[i], i + 1) > -1) {
// if element present log data and break the loop
console.log("index:", i, "value: ", numbers[i]);
break;
}
}
UPDATE : Use an object to refer the index of element would make it far better.
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11],
ref = {};
// iterate over the array
for (var i = 0; i < numbers.length; i++) {
// check value already defined or not
if (numbers[i] in ref) {
// if defined then log data and brek loop
console.log("index:", ref[numbers[i]], "value: ", numbers[i]);
break;
}
// define the reference of the index
ref[numbers[i]] = i;
}

Many good answers.. One might also do this job quite functionally and efficiently as follows;
var arr = [2,5,5,2,3,5,1,2,4],
frei = arr.findIndex((e,i,a) => a.slice(i+1).some(n => e === n)); // first repeating element index
console.log(frei)
If might turn out to be efficient since both .findIndex() and .some() functions will terminate as soon as the conditions are met.

You could use two for loops an check every value against each value. If a duplicate value is found, the iteration stops.
This proposal uses a labeled statement for breaking the outer loop.
var numbers = [1, 3, 6, 7, 5, 7, 6, 6, 4, 9, 10, 2, 11],
i, j;
outer: for (i = 0; i < numbers.length - 1; i++) {
for (j = i + 1; j < numbers.length; j++) {
if (numbers[i] === numbers[j]) {
console.log('found', numbers[i], 'at index', i, 'and', j);
break outer;
}
}
}

Move through each item and find if same item is found on different index, if so, it's duplicate and just save it to duplicate variable and break cycle
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
var duplicate = null;
for (var i = 0; i < numbers.length; i++) {
if (numbers.indexOf(numbers[i]) !== i) {
duplicate = numbers[i];
break; // stop cycle
}
}
console.log(duplicate);

var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
var map = {};
for (var i = 0; i < numbers.length; i++) {
if (map[numbers[i]] !== undefined) {
console.log(map[numbers[i]]);
break;
} else {
map[numbers[i]] = i;
}
}
Okay so let's break this down. What we're doing here is creating a map of numbers to the index at which they first occur. So as we loop through the array of numbers, we check to see if it's in our map of numbers. If it is we've found it and return the value at that key in our map. Otherwise we add the number as a key in our map which points to the index at which it first occurred. The reason we use a map is that it is really fast O(1) so our overall runtime is O(n), which is the fastest you can do this on an unsorted array.

As an alternative, you can use indexOf and lastIndexOf and if values are different, there are multiple repetition and you can break the loop;
function getFirstDuplicate(arr) {
for (var i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) !== arr.lastIndexOf(arr[i]))
return arr[i];
}
}
var arrWithNumbers = [2, 5, 5, 2, 3, 5, 1, 2, 4];
console.log(getFirstDuplicate(arrWithNumbers))
var numbers = [1, 3, 6, 7, 5, 7, 6, 6, 4, 9, 10, 2, 11]
console.log(getFirstDuplicate(numbers))

I have the same task and came up with this, pretty basic solution:
var arr = [7,4,2,4,5,1,6,8,9,4];
var firstIndex = 0;
for(var i = 0; i < arr.length; i++){
for( var j = i+1; j < arr.length; j++){
if(arr[i] == arr[j]){
firstIndex = arr[i];
break;
}
}
}
console.log(firstIndex);
First for loop takes the first element from array (number 7), then the other for loop checks all other elements against it, and so on.
Important here is to define j in second loop as i+1, if not, any element would find it's equal number at the same index and firstIndex would get the value of the last one after all loops are done.

To reduce the time complexity in the aforementioned answers you can go with this solution:
function getFirstRecurringNumber(arrayOfNumbers) {
const hashMap = new Map();
for (let number of arrayOfNumbers) { // Time complexity: O(n)
const numberDuplicatesCount = hashMap.get(number);
if (numberDuplicatesCount) {
hashMap.set(number, numberDuplicatesCount + 1);
continue;
}
hashMap.set(number, 1); // Space complexity: O(n)
}
for (let entry of hashMap.entries()) { // Time complexity: O(i)
if (entry[1] > 1) {
return entry[0];
}
}
}
// Time complexity: O(n + i) instead of O(n^2)
// Space complexity: O(n)

Using the code below, I am able to get just the first '5' that appears in the array. the .some() method stops looping through once it finds a match.
let james = [5, 1, 5, 8, 2, 7, 5, 8, 3, 5];
let onlyOneFives = [];
james.some(item => {
//checking for a condition.
if(james.indexOf(item) === 0) {
//if the condition is met, then it pushes the item to a new array and then
//returns true which stop the loop
onlyOneFives.push(item);
return james.indexOf(item) === 0;
}
})
console.log(onlyOneFives)

Create a function that takes an array with numbers, inside it do the following:
First, instantiate an empty object.
Secondly, make a for loop that iterates trough every element of the array and for each one, add them to the empty object and check if the length of the object has changed, if not, well that means that you added a element that already existed so you can return it:
//Return first recurring number of given array, if there isn't return undefined.
const firstRecurringNumberOf = array =>{
objectOfArray = {};
for (let dynamicIndex = 0; dynamicIndex < array.length; dynamicIndex ++) {
const elementsBeforeAdding = (Object.keys(objectOfArray)).length;0
objectOfArray[array[dynamicIndex]] = array[dynamicIndex]
const elementsAfterAdding = (Object.keys(objectOfArray)).length;
if(elementsBeforeAdding == elementsAfterAdding){ //it means that the element already existed in the object, so it didnt was added & length doesnt change.
return array[dynamicIndex];
}
}
return undefined;
}
console.log(firstRecurringNumberOf([1,2,3,4])); //returns undefined
console.log(firstRecurringNumberOf([1,4,3,4,2,3])); //returns 4

const arr = [1,9,5,2,3,0,0];
const copiedArray = [...arr];
const index = arr.findIndex((element,i) => {
copiedArray.splice(0,1);
return copiedArray.includes(element)
})
console.log(index);

var addIndex = [7, 5, 2, 3, 4, 5, 7,6, 2];
var firstmatch = [];
for (var i = 0; i < addIndex.length; i++) {
if ($.inArray(addIndex[i], firstmatch) > -1) {
return false;
}
firstmatch.push(addIndex[i]);
}

Related

How to find index of first duplicate in array in Javascript?

const numbers = [2, 4, 5, 2, 3, 5, 1, 2, 4];
I need to create the function indexOfRepeatedValue (array). Use numbers that are stored in the variable numbers.
I should create a variable firstIndex in this function. In the for loop, check which number repeats first and assign its index to firstIndex. Then write this variable to the console - outside of the for loop.
I came up with this idea It doesn't work at all. I'm lost, some piece of advice?
const numbers = [2, 4, 5, 2, 3, 5, 1, 2, 4];
function indexOfRepeatedValue(array) {
let firstIndex;
for (let i = 0; i < array.length; i++)
if (firstIndex.indexOf(array[i]) === -1 && array[i] !== '');
firstIndex.push(array[i]);
return firstIndex;
}
console.log(
indexOfRepeatedValue(numbers)
)
Start by making firstIndex an array: let firstIndex = [];
Then make sure the i is not outside the scope you used since you use let.
You end the statement with a semicolon, that means the loop never does the next line
Then return the first number found that is in your new array
Note JS Arrays start at 0, so the result is 3, since the second number 2 is in the 4th place
I have kept my code as close to yours as possible.
const numbers = [2, 4, 5, 2, 3, 5, 1, 2, 4];
function indexOfRepeatedValue(array) {
let firstIndex = [];
for (let i = 0; i < array.length; i++) {
if (firstIndex.indexOf(array[i]) !== -1) { // we found it
console.log("found",array[i], "again in position", i)
console.log("The first of these is in position",numbers.indexOf(array[i]))
return i; // found - the function stops and returns
// return numbers.indexOf(array[i]) if you want the first of the dupes
}
firstIndex.push(array[i]); // not found
}
return "no dupes found"
}
console.log(
indexOfRepeatedValue(numbers)
)
There are many more ways to do this
Javascript: How to find first duplicate value and return its index?
You could take an object for storing the index of a value and return early if the index exist.
function indexOfRepeatedValue(array) {
let firstIndex = {};
for (let i = 0; i < array.length; i++) {
if (firstIndex[array[i]] !== undefined) return firstIndex[array[i]];
firstIndex[array[i]] = i;
}
return -1;
}
const numbers = [2, 4, 5, 2, 3, 5, 1, 2, 4];
console.log(indexOfRepeatedValue(numbers));
Start by initializing firstIndex:
let firstIndex = [];
Use the following to find the index of each repeated element:
if( array.slice(0,i).includes(array[i]) ) {
firstIndex.push( i );
}
If you need the absolute first index of a repeat:
return firstIndex[0];
//Please note that if this is your goal then you do not even need the variable firstIndex, nor do you need to run through the whole loop.
If you need indices of all repeated elements:
return firstIndex;
const numbers = [2, 4, 5, 2, 3, 5, 1, 2, 4];
function indexOfRepeatedValue(array) {
let firstIndex = [];
for (let i = 0; i < array.length; i++)
if( array.slice(0,i).includes(array[i]) ) {
firstIndex.push(i);
}
return firstIndex[0];
}
console.log(
indexOfRepeatedValue(numbers)
)
NOTE
Alternatively, you can use Array#map to get index of repeated values then use Array#filter to retain only those indices, the first [0] is what you're lookin for.
const numbers = [2, 4, 5, 2, 3, 5, 1, 2, 4];
const indexOfRepeatedValue = arr =>
arr.map((a,i) => arr.slice(0,i).includes(a) ? i : -1)
.filter(i => i > -1)[0];
console.log( indexOfRepeatedValue( numbers ) );

printing elements from an array by alternating first and last

I'm learning for loops in JS and am trying to learn how to console.log the first and last element in an array on one iteration, then console.log the second and second to last elements, etc.
here's what I have tried:
for (let i=0; i<myArray.length; i++){
console.log(myArray[i]);
console.log(myArray[i-1];
}
This is printing elements from my array, but not in the correct order
So what you are trying to achieve is to print the last element, the second last element, etc...
You can use the myArray.length property to do it, just substract the iterator + 1 to the array length and obtain the result you want.
for (let i=0; i<myArray.length; i++){
console.log(myArray[i]);
console.log(myArray[myArray.length - (i + 1)]);
}
The (i + 1) is because the .length property returns the number of item of the array, but not the maximum index of the array. So if the length of the array is 5, the maximum index of the array is 4 (since index starts from 0). You can also write it like: myArray[myArray.length - i - 1]
Here an example:
const myArray = [1, 2, 3, 4, 5];
for (let i=0; i<myArray.length; i++){
console.log(myArray[i]);
console.log(myArray[myArray.length - (i + 1)]);
}
Create a temporary copy of your array, then use shift (to remove the head element) and pop (to remove the tail element) until the copy is empty:
const realArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const temporary = realArray.slice();
while (temporary.length) {
const e1 = temporary.shift();
// do something with e1
console.log(e1);
const e2 = temporary.pop();
if (e2) {
// note that e2 _might not exist_ so: always test
console.log(e2);
}
}
You can use two counters that works on opposite direction
i will move forward with increment as i++.
j will move backward with decrement as j--.
If there are even numbers of elements in an array then you should print both numbers arr[i] and arr[j]. But be sure to handle the odd number of elemetns in an array then you have to print either of arr[i] or arr[j]
function print(arr) {
let i = 0;
j = arr.length - 1;
while (i <= j) {
if (i !== j) {
console.log(arr[i], arr[j]);
} else console.log(arr[j]);
i++;
j--;
}
}
print([1, 2, 3, 4, 5, 6, 7, 8]);
print([1, 2, 3, 4, 5, 6, 7, 8, 9]);
Here's one way to do it, reverse the array and use the same index. Since array.reverse() mutates the original array, we slice() it in order to use a copy.
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
array.forEach((a, i) => {
let b = array.slice().reverse()[i]
if (i < array.length / 2) console.log(a, b)
})
let output = '';
for (let i = 0; i < (myArr.length) /2; i++){
output += myArr[i] + myArr[myArr.length-1-i];
}
console.log(output)
Just check for i === 0 to indicate the start of the loop and hence, you can print the last element of array
const myArray = ['first', 1, 2, 3, 'last'];
for (let i = 0; i < myArray.length - 1; i++) {
console.log(myArray[i]);
if (i === 0) {
console.log(myArray[myArray.length - 1]);
}
}

Bubble Sort with for loop doesn't work as expected

I just got started with writing sorting algorithms.
Currently I am learning the Bubble Sort algorithm, I found the following online and it's working fine:
const arr = [3, 2, 6, 9, 3, 5];
const bubbleSort = array => {
do {
var isSorted = true;
for (var i = 0; i < array.length; i++) {
if (array[i] > array[i + 1]) {
var temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
isSorted = false;
}
}
} while(!isSorted)
return array
};
Output:
[ 2, 3, 3, 5, 6, 9 ]
However, when I try to write it using an if statement instead of a while loop like the following, it doesn't work as expected:
const arr = [3, 2, 6, 9, 3, 5];
const bubbleSort = (array) => {
let isSorted = false;
if(!isSorted) {
isSorted = true;
for(var i = 0; i < array.length; i++) {
if (array[i] > array[i + 1]) {
var temp = array[i + 1];
array[i + 1] = array[i];
array[i] = temp;
isSorted = false;
}
}
}
return array;
}
Output:
[ 2, 3, 6, 3, 5, 9 ]
What am I doing wrong here?
We need the while loop for bubble sort.
If we remove while then we will 'bubble' only once through the whole array. For example if the
[3, 2, 6, 9, 3, 5];
here 3 (first element) is larger than 2 (second element) so we swap them and now we have
[2, 3, 6, 9, 3, 5]
When we continue with the for loop we approach 3 (6th element) that is smaller so we swap it with 9 (5th element). AND continue forward.
[2, 3, 6, 3, 9, 5]
from here we will only go up but we can analyse the situation. We can see that 3 (4th element) is smaller than 6(third element) but the for loop is way ahead so we will not be in a situation where we swap it with a larger element.
So we have to start "bubbling" again from the beginning and we need to do it until everything is sorted. This will happen when there are nothing to swap, because we set isSorted=false when ever we swap. After array is sorted we will do a last pass where we will check every adjacent pair and if they are all sorted the swap will not occur and isSorted will be true
TLDR; we need while because 'bubbling' might need several passes through the array.
while loop is an easy way to implement Bubble Sort, otherwise you will need O(n²) algorithm with nested for loops instead, if else statements will not work:
const arr = [3, 2, 6, 9, 3, 5];
const bubbleSort = array => {
var length = array.length;
//Number of passes
for (var i = 0; i < length; i++) {
//Notice that j < (length - i)
for (var j = 0; j < (length - i - 1); j++) {
//Compare the adjacent positions
if(array[j] > array[j+1]) {
//Swap the numbers
var tmp = array[j]; //Temporary variable to hold the current number
array[j] = array[j+1]; //Replace current number with adjacent number
array[j+1] = tmp; //Replace adjacent number with current number
}
}
}
return array
}
bubbleSort(arr)
// expected output: [2, 3, 3, 5, 6, 9]
You can also see Bubble Sort pseudocode here: Bubble Sort Algorithm

finding all missing elements in an array/range javascript

I am trying to to write a function to find all missing elements in an array. The series goes from 1...n. the input is an unsorted array and the output is the missing numbers.
below is what I have so far:
function findMissingElements(arr) {
arr = arr.sort();
var missing = [];
if (arr[0] !== 1) {
missing.unshift(1);
}
// Find the missing array items
for (var i = 0; i < arr.length; i++) {
if ((arr[i + 1] - arr[i]) > 1) {
missing.push(arr[i + 1] - 1);
}
}
return missing;
}
var numbers = [1, 3, 4, 5, 7, 8]; // Missing 2,6
var numbers2 = [5, 2, 3]; //missing 1, 4
var numbers3 = [1, 3, 4, 5, 7]; // Missing 2,6
console.log(findMissingElements(numbers)); // returns 2,6 correct
console.log(findMissingElements(numbers2)); // returns 1,4
console.log(findMissingElements(numbers3)); // returns 2, 6
I "manually" checked for the first element with an if block, is there any way to handle the case of the first element inside the for loop?
You can produce that by tracking which number should appear next and adding it to a list of missing numbers while it is less than the next number.
function findMissingElements(arr) {
// Make sure the numbers are in order
arr = arr.slice(0).sort(function(a, b) { return a - b; });
let next = 1; // The next number in the sequence
let missing = [];
for (let i = 0; i < arr.length; i++) {
// While the expected element is less than
// the current element
while (next < arr[i]) {
// Add it to the missing list and
// increment to the next expected number
missing.push(next);
next++;
}
next++;
}
return missing;
}
A not so efficient but more intuitive solution:
var n = Math.max.apply(null, arr); // get the maximum
var result = [];
for (var i=1 ; i<n ; i++) {
if (arr.indexOf(i) < 0) result.push(i)
}
Aside from the fact that your tests are not consistent, this feels a bit neater to me:
function findMissingElements (arr, fromFirstElement) {
arr.sort();
var missing = [];
var next = fromFirstElement ? arr[0] : 1;
while(arr.length) {
var n = arr.shift();
while (n != next) {
missing.push(next++);
}
next++;
}
return missing;
}
var numbers = [1, 3, 4, 5, 7, 8]; // Missing 2,6
var numbers2 = [5, 2, 3]; // Missing 1, 4
var numbers3 = [1, 3, 4, 5, 7]; // Missing 2, 6
console.log(findMissingElements(numbers)); // returns 2, 6
console.log(findMissingElements(numbers2)); // returns 1, 4
console.log(findMissingElements(numbers3)); // returns 2, 6
I've added an argument fromFirstElement which, if passed true, will enable you to start from a number defined by the first element in the array you pass.

Javascript - How Do I Check if 3 Numbers Are Consecutive and Return Starting Points?

If I have an array of [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7] and wanted to find each case of 3 consecutive numbers (whether ascending or descending), how would I do that?
Second part would be then to alert an array with the index of each of these sequences.
For ex. the previous array would return [0,4,6,7].
So far I have this... which is a rough start
var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var results = [];
for (var i = 1; i < arr.length; i++) {
if ((arr[i] - arr[i-1] != 1) && (arr[i] - arr[i+1] != 1)) {
results.push(arr[i]);
}
}
alert(results);
Thanks for the help!
Thanks for the math.abs pointer. This is what I ended up doing:
var array = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var indexes = [];
for(var i=0; i < array.length; i++) {
var diff = array[i+1] - array[i];
if(Math.abs(diff)==1 && array[i+1]+diff == array[i+2]) {
indexes.push(i);
}
}
alert(indexes);
It'd be interesting to know the context of this task as well... Anyway, here's my solution:
var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var results = [];
var limit = arr.length - 1;
var sequence = 0;
for (var i = 0; i < limit; ++i) {
var diff = arr[i+1] - arr[i];
if (sequence && sequence === diff) {
results.push(i-1);
continue;
}
sequence = (diff === 1 || diff === -1) // or ... Math.abs(diff) === 1
? diff
: 0;
}
console.log(results);
The idea is simple: we don't need to compare two neighbors twice. ) It's enough to raise a kind of sequence flag if this comparation starts a sequence, and lower it if no sequence is there.
This is a very literal approach to your question - I have only checked forwards numbers, but adding reverse would be done almost in the same way
var arr = [1, 2, 3, 4, 10, 9, 8, 9, 10, 11, 7];
var results = [];
for (var i = 0; i < arr.length; i++) {
// if next element is one more, and one after is two more
if (arr[i+1] == arr[i]+1 && arr[i+2] == arr[i]+2){
// store the index of matches
results.push(i);
// loop through next numbers, to prevent repeating longer sequences
while(arr[i]+1 == arr[i+1])
i++;
}
}
console.log(results);
You need to look closely at your expression in your if statement.
It currently says:
If the difference between the current element and previous element is not 1, and
If the difference between the current element and next element is not 1
then it's a result.
So, on the face of it, that's an incorrect logical statement to determine if the current element is in the middle of a consecutive set of three.
In addition, this doesn't account for an ascending or descending set of three either.
Try figuring out, in words, what the condition would look like and go from there.
Some things to consider
I suggest you start going through the list from i = 2
Research Math.abs
This is I think a simpler way to do it. First check the average of the left and right number is equal to the middle, then check that the absolute value of either neighbor is one.
var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var indexes = [];
for(var i=1; i < arr.length; i++) {
if((arr[i-1]+arr[i+1]) / 2 == arr[i] && Math.abs(arr[i]-arr[i-1]) == 1) {
indexes.push(i-1);
}
}
alert(indexes);
var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var results = [];
for (var i = 0; i < arr.length - 2; i++) {
if ((arr[i+1] - arr[i] === 1) && (arr[i+2] - arr[i+1] === 1)) {
results.push({
i:i,
mode:'up',
arr:[arr[i],arr[i+1],arr[i+2]
});
}
if ((arr[i+1] - arr[i] === -1) && (arr[i+2] - arr[i+1] === -1)) {
results.push({
i:i,
mode:'down',
arr:[arr[i],arr[i+1],arr[i+2]
});
}
}
alert(results);

Categories