Finding index of the last time a value occur in an array - javascript

Without using .indexOf, I'm trying to loop through an array from the end to find the last occurrence of a specific value. This is what I have so far but it keeps returning undefined.
var lastIndexOf = function (array, index) {
for (i=array.length-1; i < 0; i--) {
if (array[i] === index) {
return i;
}
}
}
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 1); //should return 3
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 2); //should return 4

Yor check is wrong, i is never smaller than zero for an index.
By the way, if you check against a value, you could use the name value instead of index, which leads to wrong assumptions and declare all variables in advance.
var lastIndexOf = function(array, value) {
var i;
for (i = array.length - 1; i >= 0; i--) {
if (array[i] === value) {
return i;
}
}
return -1; // standard default value for not found indices
};
console.log(lastIndexOf([0, 1, 4, 1, 2], 1)); // 3
console.log(lastIndexOf([0, 1, 4, 1, 2], 2)); // 4
console.log(lastIndexOf([0, 1, 4, 1, 2], 42)); // -1
A shorter approach with a while loop.
var lastIndexOf = function(array, value) {
var i = array.length
while (i--) {
if (array[i] === value) {
return i;
}
}
return -1;
};
console.log(lastIndexOf([0, 1, 4, 1, 2], 1)); // 3
console.log(lastIndexOf([0, 1, 4, 1, 2], 2)); // 4
console.log(lastIndexOf([0, 1, 4, 1, 2], 42)); // -1

Your loop condition is wrong. i will never be less than 0 unless the array is empty.
Use this instead:
(i=array.length-1; i >= 0; i--) {

You should change the check you make in the for statement. We start from the last index and we go down to the 0 index. So you loop while index >=0 and not when index<0.
I used different names for some parameters and arguments, in order to make the code more readable.
var lastIndexOf = function (array, number) {
for (var index = array.length-1; index>=0; index--) {
if (array[index] === number) {
return index;
}
}
};
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 1)); //should return 3

Related

How to return a specific value when if a value never occurs in an array function?

Trying to get this code to output -1 when value never occurs in an array.
function IndexOf (array,value) {
var index = [];
for (var i = 0; i < array.length; i++)
if (array[i] === value) {
index.push(i);
return index.pop();
} else if (value === undefined) {
return -1;
}
}
EDIT: not allowed to use .indexOf for this particular case.
EDIT 2: Sorry I wasn't more clear. I need to return the last matched element as opposed to first.
The trick to finding the last occurrence of an element is to start at the end (array.length-1) and iterate back towards the start using i--.
See return and for loop for more info.
// Index Of.
function indexOf(array, value) {
for (var i = array.length-1; i >= 0; i --) {
if (array[i] == value) return i
}
return -1
}
// Proof.
console.log(indexOf([ 0, 1, 3, 1, 2 ], 1))
console.log(indexOf([ 0, 1, 3, 1, 2 ], 2))
console.log(indexOf([ 0, 1, 3, 1, 2 ], 4))
console.log(indexOf([ 3, 3, 3 ], 3))
console.log(indexOf([], 5))
you can use indexOf function of Array object.
function checkArray(yourArray, value) {
if (yourArray.indexOf(value) > -1) {
// it means the value exists, so it has an index which is greater than -1.
// action
} else {
return -1;
}
}
You have
function IndexOf(array, value) {
// ...
} else if (value === undefined) {
return -1;
So when the second argument is ever provided, -1 will never be returned. There also isn't much point pushing to an array and then immediately popping it and returning it - just return the i itself.
Just wait until all iterations are finished instead, and then return -1.
function IndexOf(array, value) {
for (var i = 0; i < array.length; i++) {
if (array[i] === value) return i;
}
return -1;
}
console.log(IndexOf([0, 1, 3, 1, 2], 1));
console.log(IndexOf([0, 1, 3, 1, 2], 2));
console.log(IndexOf([0, 1, 3, 1, 2], 3));
console.log(IndexOf([3, 3, 3], 3));
console.log(IndexOf([], 5));
The below code works for your purpose, where returning -1 is the only other return option if the value isn't found in the array.
function IndexOf (array,value) {
var index = [];
for (var i = 0; i < array.length; i++)
if (array[i] === value) {
index.push(i);
return index.pop();
}
return -1
}
In your code, value will never equal undefined, rather value isn't located in the array and undefined is being returned due to lack of a return statement handling that condition.
Try this one. I hope this will work
function IndexOf(array, value) {
var index = [];
for (var i = 0; i < array.length; i++) {
if (array[i] === value) {
index.push(i);
}
}
if(index.length > 0){
return index.length;
} else{
return -1;
}
}
console.log(IndexOf([0, 1, 3, 1, 2], 1));
console.log(IndexOf([0, 1, 3, 1, 2], 2));
console.log(IndexOf([0, 1, 3, 1, 2], 3));
console.log(IndexOf([3, 3, 3], 3));
console.log(IndexOf([], 5));
Hopefully this snippet will be useful
function IndexOf(array, value) {
// creating an empty array
var index = [];
for (var i = 0; i < array.length; i++)
// if value matches return the index of the first matched element
if (array[i] === value) {
return i;
}
return -1
}
console.log(IndexOf([0, 1, 3, 1, 2], 1));
console.log(IndexOf([0, 1, 3, 1, 2], 2));
console.log(IndexOf([0, 1, 3, 1, 2], 3));
console.log(IndexOf([3, 3, 3], 3));
console.log(IndexOf([], 5));
function IndexOf(array, value) {
var match = -1;
for (var i = 0; i < array.length; i++)
if (array[i] === value)
match = i;
return match;
}
console.log(IndexOf([3, 3, 3], 3)); // will return 2 as the last match index is 2
console.log(IndexOf([1,2,4], 5)); // will return -1 as there is no match
I guess this is what you are looking for.

Find the number that repeat times in the no.N place

have a array such as [1,3,5,7,9,1,2,3,5,7,7,9,9,9] we can cout the times every number appear,the number 9 appear 4 time , the number 7 appear 3 time ...then how can i do to get the number that appear in no.N place ;
It mean if i want to find the no.1 it's 9,no.2 it's 7
function findFrequenceNumber(arr,n){
var count={};
for(var i=0,len=arr.length;i<len;i++){
if(!count[arr[i]]) count[arr[i]]=1;
else count[arr[i]]++;
}//I save the record in a object {num:times}
}
Try this:
var nums = [1,3,5,7,9,1,2,3,5,7,7,9,9,9];
function reArrangeByAppearingTimes(arr){
var i, appearingTimes = {}, sortableAppearingTimes = [];
// Looping over the array to get every element appearing times. sotred in OBJECT
for (i = 0; i < arr.length; i += 1){
appearingTimes[arr[i]] = appearingTimes[arr[i]] ? (appearingTimes[arr[i]] + 1) : 1;
}
// converting Object to Array (for sorting purpose)
for (var key in appearingTimes) {
sortableAppearingTimes.push([key, appearingTimes[key]]);
}
// Sorting the array
sortableAppearingTimes.sort(function(a, b) {
return b[1] - a[1];
});
// Using map to get only need values (removing appearing times)
return sortableAppearingTimes.map(function (smallArr) {
return smallArr[0]
});
}
console.log(reArrangeByAppearingTimes(nums));
You could get all keys form the object,sort it descending and take the wanted item at the nth position.
function findFrequenceNumber(arr, n){
var count = {}, keys;
for (var i = 0, len = arr.length; i < len; i++){
if(!count[arr[i]]) {
count[arr[i]] = 1;
} else {
count[arr[i]]++;
}
}
keys = Object.keys(count).sort(function (a, b) { return count[b] - count[a]; });
console.log('keys', keys);
return keys[n - 1];
}
console.log(findFrequenceNumber([1, 3, 5, 7, 9, 1, 2, 3, 5, 7, 7, 9, 9, 9], 1));
console.log(findFrequenceNumber([1, 2, 3, 3, 1, 1, 1, 1], 1));

Find a group of objects in an array with javascript

Question has been moved to CodeReview: https://codereview.stackexchange.com/questions/154804/find-a-list-of-objects-in-an-array-with-javascript
Having an array of objects - such as numbers - what would be the most optimal (Memory and CPU efficiency) way if finding a sub group of objects? As an example:
demoArray = [1,2,3,4,5,6,7]
Finding [3,4,5] would return 2, while looking for 60 would return -1.
The function must allow for wrapping, so finding [6,7,1,2] would return 5
I have a current working solution, but I'd like to know if it could be optimized in any way.
var arr = [
1,
5,2,6,8,2,
3,4,3,10,9,
1,5,7,10,3,
5,6,2,3,8,
9,1]
var idx = -1
var group = []
var groupSize = 0
function findIndexOfGroup(g){
group = g
groupSize = g.length
var beginIndex = -2
while(beginIndex === -2){
beginIndex = get()
}
return beginIndex
}
function get(){
idx = arr.indexOf(group[0], idx+1);
if(idx === -1 || groupSize === 1){
return idx;
}
var prevIdx = idx
for(var i = 1; i < groupSize; i++){
idx++
if(arr[getIdx(idx)] !== group[i]){
idx = prevIdx
break
}
if(i === groupSize - 1){
return idx - groupSize + 1
}
}
return -2
}
function getIdx(idx){
if(idx >= arr.length){
return idx - arr.length
}
return idx
}
console.log(findIndexOfGroup([4,3,10])) // Normal
console.log(findIndexOfGroup([9,1,1,5])) // Wrapping
You could use the reminder operator % for keeping the index in the range of the array with a check for each element of the search array with Array#every.
function find(search, array) {
var index = array.indexOf(search[0]);
while (index !== -1) {
if (search.every(function (a, i) { return a === array[(index + i) % array.length]; })) {
return index;
}
index = array.indexOf(search[0], index + 1);
}
return -1;
}
console.log(find([3, 4, 5], [1, 2, 3, 4, 5, 6, 7])); // 2
console.log(find([6, 7, 1, 2], [1, 2, 3, 4, 5, 6, 7])); // 5
console.log(find([60], [1, 2, 3, 4, 5, 6, 7])); // -1
console.log(find([3, 4, 5], [1, 2, 3, 4, 6, 7, 3, 4, 5, 9])); // 6
.as-console-wrapper { max-height: 100% !important; top: 0; }
My take on the problem is to use slice() and compare each subarray of length equal to the group's length to the actual group array. Might take a bit long, but the code is short enough:
// The array to run the tests on
var arr = [
1,
5, 2, 6, 8, 2,
3, 4, 3, 10, 9,
1, 5, 7, 10, 3,
5, 6, 2, 3, 8,
9, 1
];
// Check arrays for equality, provided that both arrays are of the same length
function arraysEqual(array1, array2) {
for (var i = array1.length; i--;) {
if (array1[i] !== array2[i])
return false;
}
return true;
}
// Returns the first index of a subarray matching the given group of objects
function findIndexOfGroup(array, group) {
// Get the length of both arrays
var arrayLength = array.length;
var groupLength = group.length;
// Extend array to check for wrapping
array = array.concat(array);
var i = 0;
// Loop, slice, test, return if found
while (i < arrayLength) {
if (arraysEqual(array.slice(i, i + groupLength), group))
return i;
i++;
}
// No index found
return -1;
}
// Tests
console.log(findIndexOfGroup(arr,[4,3,10])); // Normal
console.log(findIndexOfGroup(arr,[9,1,1,5])); // Wrapping
console.log(findIndexOfGroup(arr,[9,2,1,5])); // Not found
If the group is longer than the array, some errors might occur, but I leave it up to you to extend the method to deal with such situations.

How to find and log the longest repeating serie of numbers in array with javascript

My problem is I can't console.log the repeating after another same numbers in the array. I can find which number how many times appears with this code:
var array = [2, 1, 1, 2, 3, 3, 2, 2, 2, 1],
currentNum = 1,
counter = 0,
item;
for (var i = 0; i < array.length; i++) {
for (var j = i; j < array.length; j++) {
if (array[i] == array[j])
counter++;
if (currentNum < counter) {
currentNum = counter;
item = array[i];
}
}
counter = 0;
}
console.log(item + " ( " + currentNum + " times ) ");
But my real issue is that I want to log the 2, 2, 2 part and I don't know how.
Thank you guys very much in advance!
Following will find the first instance of longest (assuming more than one same length sequence)
The first reduce() creates subarrays for each sequence, the second reduce() checks lengths of those sub arrays returning the first instance of longest sequence
var array = [2, 1, 1, 2, 3, 3, 2, 2, 2, 1];
var res = array.reduce(function(a,c,i){
if(a.length && a[a.length-1][0] ===c){
a[a.length-1].push(c)
}else{
a.push([c]);
}
return a
},[]).reduce(function(a,c){
return c.length > a.length ? c : a;
});
console.log('Sequence length=',res.length);
console.log('Value=', res[0]);
If you expect multiple same length sequences and want to capture all the values that match can modify second reduce something like:
var array = [2, 1, 1, 2, 3, 3, 2, 2, 2, 1, 2, 2, 2, 7, 7, 7];
var res = array.reduce(function(a,c,i){
if(a.length && a[a.length-1][0] ===c){
a[a.length-1].push(c)
}else{
a.push([c]);
}
return a
},[]).reduce(function(a,c){
if(c.length > a.len){
// reset when longer sequence found
a.values = [c[0]];
a.len = c.length;
} else if(c.length === a.len){
// add new value when same length found
a.values.push(c[0]);
}
return a
},{len:0,values:[]});
console.log('Sequence length=', res.len)
console.log('How many times=', res.values.length)
console.log('Values = ', res.values.join() )
Array.prototype.forEach or reduce is better for iteration through an array.
Here is a solution with a single going through array (just 3 additional variables :) )
var array = [2, 1, 1, 2, 3, 3, 2, 2, 2, 1]
var item = array[0], maxTimes = 1, currentTimes = 1
array.reduce(function(prev, current) {
if (prev === current) {
currentTimes = currentTimes + 1
if (currentTimes > maxTimes) {
maxTimes = currentTimes
item = current
}
} else {
currentTimes = 1
}
return current
})
console.log(item, maxTimes)
You could use Array#reduce with an object which holds the temporary result and the actual count of the item.
If an item is equal to the last item, last count is incremented and checked if the count is greater than the temporary count. Then the temporary count is replaced by the actual count.
var array = [2, 1, 1, 2, 3, 3, 2, 2, 2, 1],
count = array.reduce(function (r, a, i, aa) {
if (a === aa[i - 1]) {
r.last.count++;
if (!(r.last.count <= r.result.count)) {
r.result = r.last;
}
} else {
r.last = { value: a, count: 1 };
}
return r;
}, { last: {}, result: {} }).result;
console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Remove smallest number in JS Array

I have a number array [2, 1, 3, 4, 5, 1] and want to remove the smallest number in the list. But somehow my IF statement gets skipped.
I checked and by itself "numbers[i + 1]" and "numbers[i]" do work, but "numbers[i + 1] < numbers[i]" doesn't...
function removeSmallest(numbers) {
var smallestNumberKEY = 0;
for (i = 0; i <= numbers.lenths; i++) {
if (numbers[i + 1] < numbers[i]) {
smallestNumberKEY = i + 1;
}
}
numbers.splice(smallestNumberKEY, 1);
return numbers;
}
document.write(removeSmallest([2, 1, 3, 4, 5, 1]));
You have a typo in your code, array doesn't have lenths property
function removeSmallest(numbers) {
var smallestNumberKEY = 0;
for (var i = 0; i < numbers.length - 1; i++) {
if (numbers[i + 1] < numbers[i]) {
smallestNumberKEY = i + 1;
numbers.splice(smallestNumberKEY, 1);
}
}
return numbers;
}
document.write(removeSmallest([2, 1, 3, 4, 5, 1]));
But your algorithm wont work for another array, e.g [5, 3, 1, 4, 1], it will remove a value 3 too.
You can find the min value with Math.min function and then filter an array
function removeSmallest(arr) {
var min = Math.min(...arr);
return arr.filter(e => e != min);
}
You can use Array#filter instead
function removeSmallest(arr) {
var min = Math.min.apply(null, arr);
return arr.filter((e) => {return e != min});
}
console.log(removeSmallest([2, 1, 3, 4, 5, 1]))
Short one liner. If the smallest value exist multiple times it will only remove ONE. This may or may not be what you want.
const result = [6,1,3,1].sort().filter((_,i) => i) // result = [1,3,6]
It works by sorting and then creating a new array from the items where indeces are truthy(anything but 0)
another solution with splice and indexOf:
array = [2, 1, 3, 4, 5, 1];
function replace(arr){
arr = arr.slice(); //copy the array
arr.splice( arr.indexOf(Math.min.apply(null, arr)),1)
return arr;
}
document.write( replace(array) ,'<br> original array : ', array)
edit : making a copy of the array will avoid the original array from being modified
"Short" solution using Array.forEach and Array.splice methods:
function removeSmallest(numbers) {
var min = Math.min.apply(null, numbers);
numbers.forEach((v, k, arr) => v !== min || arr.splice(k,1));
return numbers;
}
console.log(removeSmallest([2, 1, 3, 4, 5, 1])); // [2, 3, 4, 5]
This is a proposal with a single loop of Array#reduce and without Math.min.
The algorithm sets in the first loop min with the value of the element and returns an empty array, because the actual element is the smallest value and the result set should not contain the smallest value.
The next loop can have
a value smaller than min, then assign a to min and return a copy of the original array until the previous element, because a new minimum is found and all other previous elements are greater than the actual value and belongs to the result array.
a value greater then min, then the actual value is pushed to the result set.
a value equal to min, then the vaue is skipped.
'use strict';
var removeSmallest = function () {
var min;
return function (r, a, i, aa) {
if (!i || a < min) {
min = a;
return aa.slice(0, i);
}
if (a > min) {
r.push(a);
}
return r;
}
}();
document.write('<pre>' + JSON.stringify([2, 1, 3, 2, 4, 5, 1].reduce(removeSmallest, []), 0, 4) + '</pre>');
I like this oneliner: list.filter(function(n) { return n != Math.min.apply( Math, list ) })
check it out here: https://jsfiddle.net/rz2n4rsd/1/
function remove_smallest(list) {
return list.filter(function(n) { return n != Math.min.apply( Math, list ) })
}
var list = [2, 1, 0, 4, 5, 1]
console.log(list) // [2, 1, 0, 4, 5, 1]
list = remove_smallest(list)
console.log(list) // [2, 1, 4, 5, 1]
list = remove_smallest(list)
console.log(list) // [2, 4, 5]
I had to do this but I needed a solution that did not mutate the input array numbers and ran in O(n) time. If that's what you're looking for, try this one:
const removeSmallest = (numbers) => {
const minValIndex = numbers.reduce((finalIndex, currentVal, currentIndex, array) => {
return array[currentIndex] <= array[finalIndex] ? currentIndex : finalIndex
}, 0)
return numbers.slice(0, minValIndex).concat(numbers.slice(minValIndex + 1))
}
function sumOfPaiars(ints){
var array = [];
var min = Math.min(...ints)
console.log(min)
for(var i=0;i<ints.length;i++){
if(ints[i]>min){
array.push(ints[i])
}
}
return array
}
If you only wish to remove a single instance of the smallest value (which was my use-case, not clear from the op).
arr.sort().shift()
Here is a piece of code that is work properly but is not accepted from codewars:
let numbers = [5, 3, 2, 1, 4];
numbers.sort(function numbers(a, b) {
return a - b;
});
const firstElement = numbers.shift();

Categories