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();
Related
I have an array with numbers. Need to find how many elements from the beginning of the array must be added to get a total of more than 10. In the code I have to use reduce
let arr = [2, 3, 1, 0, 4, 5, 4];
The console in this case must display the number 6.
My code didn't work:
let arr = [2, 3, 1, 0, 4, 5, 4];
let sumNumber = arr.reduce((sum, elem, index) => {
let ourSum = 0;
while (ourSum <= 10) {
return sum + elem;
}
index++
}, 0)
console.log(sumNumber);
You could find the index and add one.
This iteration stops if the comparison is true.
let array = [2, 3, 1, 0, 4, 5, 4],
index = array.find((sum => value => (sum += value) > 10)(0));
console.log(index + 1);
let arr = [2, 3, 1, 0, 4, 5, 4];
// i is to store the element count at which it gets greater than 10
let i=0;
let sumNumber = arr.reduce((sum, elem, index) => {
// Checks if sum is greater than 10 yet?
if(sum>=10){
// this condn below will only evaluate once when for the
// first time the sum is greater than or equal to 10
if(i===0) i=index+1;
}
// updates the sum for every loop run
return sum+elem;
});
console.log("Element count for which sum is greater than equal to 10 is:",i);
This is one solution:
const arr = [2, 3, 1, 0, 4, 5, 4]
const sumNumber = arr.reduce(
(acc, cur, index) => {
if (typeof acc === 'number') { // If the accumulator is a number...
return acc // Just return it
}
const sum = acc.sum + cur
if (sum > 10) { // If sum is greater than 10...
return index + 1 // ...return a number
}
return { sum } // Return an object with sum with the new value
},
{ sum: 0 } // Start with an object with the `sum` property of 0
)
console.log(sumNumber)
You can do this with some method, you do not have to loop through the rest of the elements when condition is achived.
var arr = [2, 3, 1, 0, 4, 5, 4];
var obj = {sum : 0, index : 0 };
arr.some((k,i)=>{
obj.sum+=k;
if(obj.sum > 10) {
obj.index = i+1;
return true
}
});
console.log(obj)
I'd like to combine identical elements in an array, into a single term with how many times the value appears
function combineArrayElements(arr) {
return arr.map((e, i, ar) => {
if (e === ar[i + 1] || (e[0] && e[0] === ar[i + 1])) {
return [e, e[1] + 1]
}
return e;
})
}
Some example input and output:
// input [3, 2, 2, 5, 1, 1, 7, 1]
// output [3,[2,2],5,[1,2],7,1]
// input [1, 1, 1, 2, 1]
// output [[1,3], 2, 1]
You could reduce the array and if the value is equal the last value, take an array and increment the counter.
const
getGrouped = array => array.reduce((r, v, i, { [i - 1]: last }) => {
if (v === last) {
if (!Array.isArray(r[r.length - 1])) r[r.length - 1] = [r[r.length - 1], 1];
r[r.length - 1][1]++;
} else {
r.push(v);
}
return r;
}, []);
console.log(getGrouped([3, 2, 2, 5, 1, 1, 1, 7, 1]));
console.log(getGrouped([2, 2, 2, 3]));
Thank, Joseph Cho - answer is:
function splitCounts(arr) {
let res = [];
let count = 1;
for (let i=0; i<arr.length; i++) {
if (arr[i] === arr[i+1]) {
count++;
} else {
res.push([arr[i], count]);
count = 1;
}
}
return res;
}
// [[3,1],[2,2],[5,1],[1,2],[7,1],[1,1]]
console.log(splitCounts([3,2,2,5,1,1,7,1]));
Refactored Nina Scholz's answer with longer variable names, comments, and slightly different control of flow:
const combineAdjacentElements = array => array.reduce((acc, val, i) => {
// if cur is different from prev value, add raw number
if (val !== array[i - 1]) {
acc.push(val)
return acc
}
// if first repetition, replace val with grouped array
if (typeof acc.at(-1) === 'number') {
acc[acc.length - 1] = [val, 2];
return acc
}
// if multiple repetition, increment counter in grouped array
acc.at(-1)[1]++;
return acc;
}, []);
const output = combineAdjacentElements([3, 2, 2, 2, 5, 1, 1, 7, 1])
console.log(JSON.stringify(output, null, 0))
// [3,[2,3],5,[1,2],7,1]
Further Reading
Check whether variable is number
How the get the last element in an array
How to replace the last index value in array javascript
Just use Array.reduce()
to get that.
i have an array for example [10, 5, 6, 3], also a variable b = 13, I wanna calculate the sum of each element of the array, if the sum equal = b(13) returns true, i know first and last elements sum = 13. How can I check which pair of element's sum?
You could take a hash table for the missing parts and return if found.
function check(array, sum) {
var hash = {},
i = 0,
v;
while (i < array.length) {
v = array[i];
if (hash[v]) return true;
hash[sum - v] = true;
++i;
}
return false;
}
console.log(check([10, 5, 6, 3], 13));
console.log(check([10, 5, 6, 3], 17));
You can use this algorithm to check if two values in array have the given sum or not.
function pairWithSum(array,sum){
//sort the array
const arr = array.sort((a,b) => a -b);
while(arr.length > 1){
if(arr[0] + arr[arr.length - 1] > sum) arr.pop()
if(arr[0] + arr[arr.length - 1] < sum) arr.shift()
if(arr[0] + arr[arr.length - 1] === sum) return true
}
return false;
}
console.log(pairWithSum([10,3,5,6,1],1))
console.log(pairWithSum([10,3,5,6,1],11))
console.log(pairWithSum([10,3,5,6,1],13));
console.log(pairWithSum([10,3,5,6,1],55))
How to find the difference between the min and max indexes of the same value in an array with one loop with complexity exactly O(N)?
For example, given array A:
[4, 6, 2, 2, 6, 6, 1];
the function returns 4.
I'd use reduce to remember the first index of each value, then update the last value and maximum spread as I went along, e.g.
var data = [4, 6, 2, 2, 6, 6, 1];
function getMaxIndexSpread(data) {
return data.reduce(function(acc, value, index) {
if (value in acc) {
acc[value].lastIndex = index
} else {
acc[value] = {firstIndex: index, lastIndex: index};
}
var spread = acc[value].lastIndex - acc[value].firstIndex;
if (acc.maxSpread < spread) acc.maxSpread = spread;
return acc;
}, {maxSpread: 0}).maxSpread;
}
console.log(getMaxIndexSpread(data));
There's likely a funkier way, but this makes sense to me.
var data = [4, 6, 2, 2, 6, 6, 1];
console.log(Math.max(...data.map((v,i) => i - data.indexOf(v))));
var arr = [4, 6, 2, 2, 6, 6, 1];
function test(arr) {
var resultArr = [];
arr.map(function (v, i, a) {
for (var j = arr.length - 1; j >= 0; j--) {
if (v == arr[j]) {
resultArr.push({value: v, result: j - i});
// console.log(v+'的折扣值'+(j-i));
break;
}
}
})
resultArr.sort(function (a, b) {
return b.result - a.result;
})
console.log(resultArr[0])
}
test(arr);
Try with Array#filter .filter the array without max and min value .Then find max value in filtered array .... its spread syntax
var data = [4, 6, 2, 2, 6, 6, 1];
function bet(data) {
return Math.max(...data.filter(a => a != Math.max(...data) && a != Math.min(...data)))
}
console.log(bet(data))
I'm not sure if the title of this question is correct or not and also not sure what the appropriate keyword to search on google.
I have an array look like:
var myArray = [1,1,2,2,2,3,4,4,4];
and I want to sort my array into:
var myArray = [1,2,3,4,1,2,4,2,4];
Please in to my expected result. the order is ascending but duplicate value will repeated on last sequence instead of put it together in adjacent keys. So the expected result grouped as 1,2,3,4 1,2,4 and 2,4.
Thank you for your help and sorry for my bad English.
This code works. But it may exist a better solution.
// We assume myArray is already sorted
var myArray = [1,1,2,2,2,3,4,4,4],
result = [];
while (myArray.length) {
var value = myArray.shift();
// Find place
var index = 0;
while(result[index] && result[index][result[index].length - 1] == value) index++;
if(!result[index]) {
result[index] = [];
}
result[index][result[index].length] = value;
}
result.reduce(function(current, sum) {
return current.concat(sum);
});
console.log(result) // Display [1, 2, 3, 4, 1, 2, 4, 2, 4]
Here is my method using JQuery and it does not assume the array is already sorted.
It will iterate through the array and no duplicates to tempResultArray, once finished, it will then add them to the existing result and repeat the process again to find duplicates.
This is not the most efficient method, but it can be handled by one function and does not require the array to be sorted.
var myArray = [1,1,2,2,2,3,4,4,4],result = [];
while (myArray && myArray.length) {
myArray = customSort(myArray);
}
console.log(result);
function customSort(myArray){
var tempResultArray = [], tempMyArray = [];
$.each(myArray, function(i, el){
if($.inArray(el, tempResultArray ) === -1){
tempResultArray.push(el);
}else{
tempMyArray.push(el);
}
});
tempResultArray.sort(function(a, b){return a-b});
$.merge( result,tempResultArray)
return tempMyArray;
}
JSFiddle
This proposal features a straight forward approach with focus on array methods.
function sprout(array) {
return array.reduce(function (r, a) {
!r.some(function (b) {
if (b[b.length - 1] < a) {
b.push(a);
return true;
}
}) && r.push([a]);
return r;
}, []).reduce(function (r, a) {
return r.concat(a);
});
}
document.write('<pre>' + JSON.stringify(sprout([1, 1, 2, 2, 2, 3, 4, 4, 4]), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(sprout([1, 2, 3, 7, 7, 7]), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(sprout([1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 6, 6, 6, 7]), 0, 4) + '</pre>');
here's another solution:
var myArray = [1, 1, 2, 2, 2, 3, 4, 4, 4];
function mySequelArray(arr) {
var res = arguments[1] || [];
var nextVal;
var min = Math.min.apply(null, arr);
if (res.length > 0) {
nextVal = arr.filter(function (x) {
return x > res[res.length - 1]
}).sort()[0] || min;
} else {
nextVal = min;
}
res.push(nextVal);
arr.splice(arr.indexOf(nextVal), 1);
return (arr.length > 0) ? mySequelArray(arr, res) : res;
}
console.log(mySequelArray(myArray))
fiddle
My best approach will be to split your array into separate arrays for each repeated value, then arrange each separate array and join altogether.
UPDATED:
I wrote a quick code sample that should work if the same number in inputArray is not given more than twice. You could improve it by making it recursive thus creating new arrays for each new number and removing the limitation. Had some free time so i re-wrote a recursive function to sort any given array in sequence groups like you wanted. Works like a charm, inputArray does not need to be sorted and doesn't require any libraries. Jsfiddle here.
var inputArray = [3, 4, 1, 2, 3, 1, 2, 4, 1, 2, 5, 1];
var result = sortInSequence(inputArray);
console.log(result); //output: [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 1]
function sortInSequence(inputArray){
var inputArraySize = inputArray.length,
tempArray = [], //holds new array we are populating
sameValuesArray = [], //holds same values that we will pass as param in recursive call
rSorted = []; //init sorted array in case we have no same values
for(var i = inputArraySize; i > 0; i--){
var value = inputArray.pop();
tempArray.push(value);
var counter = 0,
tempArraySize = tempArray.length;
for(var j = 0; j < tempArraySize; j++){
if(tempArray[j] == value){
counter++;
}
}
if(counter == 2){
//value found twice, so remove it from tempArray and add it in sameValuesArray
var sameValue = tempArray.pop();
sameValuesArray.push(sameValue);
}
}
if(sameValuesArray.length > 0){
rSorted = sortInSequence(sameValuesArray);
}
tempArray.sort();
return tempArray.concat(rSorted);
}