I have a question. I'm looking for a way to get the higest unique number of an array.
var temp = [1, 8, 8, 8, 4, 2, 7, 7];
Now I want to get the output 4 since that is the unique highest number.
Is there a good & hopefully short way to do that?
Yes, there is:
Math.max(...temp.filter(el => temp.indexOf(el) == temp.lastIndexOf(el)))
Explanation:
First, get the elements which are unique in the array using Array#filter
temp.filter(el => temp.indexOf(el) === temp.lastIndexOf(el)) // [1, 4, 2]
Now, get the max of the numbers from the array using ES6 spread operator
Math.max(...array) // 4
This code is equivalent to
Math.max.apply(Math, array);
If you don't want to get fancy, you can use a sort and loop to check the minimal number of items:
var max = 0;
var reject = 0;
// sort the array in ascending order
temp.sort(function(a,b){return a-b});
for (var i = temp.length - 1; i > 0; i--) {
// find the largest one without a duplicate by iterating backwards
if (temp[i-1] == temp[i] || temp[i] == reject){
reject = temp[i];
console.log(reject+" ");
}
else {
max = temp[i];
break;
}
}
Using the spread operator you can find the hightest number easily
Math.max(...numArray);
The only thing left then is to either filter duplicates from the array beforehand, or remove all the elements that match your maximum number if its a duplicate.
remove beforeHand would be easiest in es6 like this.
Math.max(...numArray.filter(function(value){ return numArray.indexOf(value) === numArray.lastIndexOf(numArray);}));
For a non es6 compatible way to remove duplicates have a look at Remove Duplicates from JavaScript Array, the second answer contains an extensive examinations of several alternatives
Related
This question already has answers here:
How to delete an item from state array?
(18 answers)
Closed 5 years ago.
I've made this post last year and today, I assume things can be simplified.
I need to remove an item from an array but by the index. When by the index, it does not matter if the array has same values. Your typical example:
let arr = [1,2,3,2,1] // just an array, not array with objects
let x = 1;
// This will not be an expected result:
// Find all values that is equal to 1 then remove
arr.filter(num => num !== x) //=> [2,3,2]
My expectation is when I remove the last element (1), for example, the array should be [1,2,3,2]:
let index = 4; // which is the last "1" in the array
let indexVal = arr.indexOf(4) // 1
let newArray = arr.splice(indexVal, 1) //=> [1,2,3,2]
Now, it's 2017, almost '18, is there a shorter way (es5/6) of doing this without any polyfil?
Edit:
Think of this as a todo:
<ul>
<li>me</li>
<li>me</li> // click to delete this one
<li>you</li>
<li>me</li>
</ul>
To correctly remove that item, I have to delete by the index not value
The Array.filter callback gives 2 arguments, number and index and you can filter the array this way.
let arr = [1,2,3,2,1]
let x = 4; //suppose you want to remove element at 4th index
let editedArray = arr.filter((num, index) => index !== x) //editedArray = [1,2,3,2]
EDIT:
The third parameter gives the whole array. Thanks #Oliver for pointing this out in comment
arr.splice(index, 1);
or if you specifically want to remove the last element:
arr.pop();
No indexOf call. The indexOf call never should have been there; it only ever looked like it worked because indexOf returns -1 for an element that isn't present, and splice treats negative indices as counting from the end of the array.
Also, splice modifies the array in place and returns an array of removed elements, so assigning its return value the way you were doing is misleading.
The only way I can think of is the one we use in Redux every day:
const arr = [1, 2, 3, 2, 1]
const index = 4 // index of the item you want to remove
const newArr = [...arr.slice(0, index), ...arr.slice(index + 1)]
console.log(newArr) // [1, 2, 3, 2]
It might not be the shortest but it is more 2017 and it is immutable, which is very important!
Ajay's answer might be what you're looking for. Anyway, there are people like me who prefer slightly-more-lines-but-more-readable/rewritable/maintable solution, I'd do it this way:
function removeElementByIndex(arr, x) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
if(i != x) {
newArr.push(arr[i]);
}
}
return newArr;
}
// Usage
removeElementByIndex([1, 2, 3, 2, 1], 4);// outputs: [1, 2, 3, 2]
Now, it's 2017, almost '18, is there a shorter way (es5/6) of doing
this without any polyfil?
LOL! Many basic things not yet implemented. We'll have to wait for 2118 or another programming language to replace JS (oh wait, there's one, aka jQuery :P ).
var myArray = [1,2,3,4,5,6,7,8,9];
function isOdd(value){
return value % 2;
}
for(var i = 0; i < myArray.length; i++){
if(isOdd(myArray[i])){
myArray.splice(i,1);
i--;
}
}
The code above takes an array of arbitrary length and checks each value. If the value of the bit of the array meets an arbitrary condition (in this case if it is odd), then it is removed from the array.
Array.prototype.splice() is used to remove the value from the array, and then i is decremented to account for the rest of the values in the array "moving down" to fill in the gap that the removed value left (so the loop doesn't skip over a value).
However, the for loop ends when i equals the length of the array, which gets shorter as values are removed.
Does the value of myArray.length decrease dynamically as the loop proceeds, or does it save the value at the start of the loop and not update as values are removed? If the latter, what can I do to fix my loop?
Thank you!
myArray.length is changing with the operation on the array. But looping and splicing leads to unwanted results, if not proper padded.
To prevent unnecessary corrections, use a while loop from the end, to keep the rest of the array for processing.
function isOdd(value) {
return value % 2;
}
var myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9],
i = myArray.length;
while (i--) {
if (isOdd(myArray[i])) {
myArray.splice(i, 1);
}
}
console.log(myArray);
The length property is read in every iteration, and the splice method does update its value, so it works as you would expect. However, I would say that this is not a good coding practice, a while loop is much more readable, so it should be the obvious choice.
To answer the question directly: you don't have to use while instead of for, but you definitely should.
Use Array.filter instead
var myArray = [1,2,3,4,5,6,7,8,9];
myArray=myArray.filter(function(item,index) {
return !(item % 2);
})
console.log(myArray)
This is where you'd want to use Array.prototype.filter() if you don't absolutely HAVE to modify the original array, in-place.
As you suspect, the .length property of the array is being updated every time you splice(). The filter() method was built for exactly this sort of operation.
var myArray = [1,2,3,4,5,6,7,8,9];
function isOdd(value){
return value % 2;
}
var filteredArray = myArray.filter(function(item){
return !isOdd(item);
});
console.log(filteredArray);
A more concise version of the above code:
var myArray = [1,2,3,4,5,6,7,8,9];
function isEven(value){
return value % 2 === 0;
}
var filteredArray = myArray.filter(isEven);
console.log(filteredArray);
An even more concise version relying on ES6 arrow syntax:
var myArray = [1,2,3,4,5,6,7,8,9];
var isEven = value => value % 2 === 0;
var filteredArray = myArray.filter(isEven);
console.log(filteredArray);
And, in the event that you absolutely MUST edit the array in-place / use splice() here, I would recommend using Array.prototype.forEach() over a for or while loop. forEach() is another higher order method that allows you to realize the same functionality with less boilerplate. As with most higher order methods/functions, it allows you to focus on defining what you need to do rather than exactly how it needs to be done.
var myArray = [1,2,3,4,5,6,7,8,9];
function isOdd(value){
return value % 2;
}
myArray.forEach(function(c, i, a){
if(isOdd(c)){
a.splice(i,1);
}
})
console.log(myArray);
You can use both of them and it's depends on which one you like. if you prefer to use while loop then Nina's answer looks good and if you want to use for loop then consider to manage counter changes by yourself completely or when the length changes:
function isOdd(value) {
return value % 2;
}
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr1.length;)
isOdd(arr1[i]) ? arr1.splice(i, 1) : i++;
console.log(arr1);
var arr2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr2.length; i++)
if (isOdd(arr2[i])) {
arr2.splice(i, 1);
i--;
}
console.log(arr2);
This question already has answers here:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
(97 answers)
Closed 8 years ago.
Here is my question...
Given an array populated with numbers as a function parameter, produce a resulting array which contains any duplicates number from the array.
For example, given the array [ 1, 2, 4, 4, 3, 3, 1, 5, 3 ] it should return [1, 4, 3]. For extra bonus points return a sorted array.
I am starting out with Javascript - I know the language however, using it in the correct way ( as one should ) I'm still getting to grips with.
My pseudo code for this would be to:
Create an array with the numbers above var numbers = [1, 2, 4, 4, 3, 3, 1, 5, 3];
Then create an empty array named "result" var result = [];
Create a for loop that goes through the var numbers to check for duplicates which will then populate the empty array "result" with the duplicates
for (var i = 0;i < numbers.length; i++) {
//This is where I'm stuck...
}
I'm not sure what to do within the for loop to populate the var result and to throw in to the mix... The given array has to be a function parameter which makes sense so you can change the numbers in one place.
Any feedback on my thought process on this so far is greatly appreciated but ultimately I am wanting to learn how to achieve this.
Here is a JSFiddle of my progress so far... http://jsfiddle.net/fbauW/
One way of doing this (and it's not the only way) is by checking for existing elements in the array. Take a look at JavaScript's lastIndexOf function:
http://www.w3schools.com/jsref/jsref_lastindexof_array.asp
It will return -1 if the object does not exist in your array, and if it exists, will return an index of a later position than you are in. So you can use an if statement in your loop that checks whether or not there is another index containing your number, and add it in to your results array IF AND ONLY IF the index you get back != the index you are currently on (if they equal, this means that there is only one of that element in the list).
If you need more help, comment here and I can type some code in!
Good luck!
Array.prototype.contains = function(k) {
for ( var p in this)
if (this[p] === k)
return true;
return false;
};
//this prototype function checks if an element is already in the array or not
//go through all the array and push the element to result if it is not
//this way we can eliminate duplicates
//result will contain the resultant array
function findDuplicates(Numbers) {
var arrayLength = Numbers.length, i, j, result = [];
for (i = 0; i < arrayLength; i++) {
for (j = 0; j < arrayLength; j++) {
if (a[i] == a[j] && i != j && !result.contains(a[i])) {
result.push(a[i]);
}
}
}
return result;
}
Pretty basic question but I can't seem to find any examples of how to solve it in Javascript.
I would like to create a function where you pass a number representing "n" and it returns the location of the nth smallest number in the array.
For instance, if I did:
array = [5,6,1,1,1,8]
n = 3
location = nth_smallest(array, n)
Location would then be equal to 4, because the third lowest number is 1 however I would like to skip the first several duplicates of that number.
The common solution to finding the location of the nth smallest number is by doing:
array = [5,6,1,1,1,8]
n = 3
nth_lowest = array.slice(0).sort()[n]
location = $.inArray(nth_lowest, array)
However the problem is that it will always return the location being 2 because it knows that the third smallest number is 1 but the inArray function doesn't care about duplicates.
Is there any way to do this, possibly without using the sort function? It seems to take up a lot of processing and this is a function that will be run quite often.
// remap array as pairs of value and index
// e.g. change [5, 6, 1] to [[5, 0], [6, 1], [1, 2]]
var augmented_array = array.map(function(val, index) { return [val, index]; });
// sort pairs by the first position, breaking ties by the second
augmented_array.sort(function(a, b) {
var ret = a[0] - b[0];
if (ret == 0) ret = a[1] - b[1];
return ret;
});
// example array will now be [[1, 2], [5, 0], [6, 1]]
// so we get the location by just looking at the second position of a pair
var location = augmented_array[n - 1][1];
If you want the last location having that value, after the sort do:
var position = n - 1;
while (position < augmented_array.length - 1 &&
augmented_array[position][0] == augmented_array[position + 1][0]) {
++position;
}
var location = augmented_array[position][1];
Or if you want the first location, do:
var position = n - 1;
while (position > 0 &&
augmented_array[position][0] == augmented_array[position - 1][0]) {
--position;
}
var location = augmented_array[position][1];
Of course, lastIndexOf or indexOf, as suggested by one of the other answers would result in less code.
If I understand your question correctly, you are looking for the position of the last instance of the n-th lowest number? If so, try this:
array = [5,6,1,1,1,8];
n = 3;
nth_smallest = array.slice(0).sort()[n];
location = array.lastIndexOf(nth_smallest); // assumes non-ancient browser and/or shim
A haxy shim of lastIndexOf could be done like so:
function lastIndexOf(array,item) {
return array.join("\x00").match(new RegExp(".*\x00"+item+"\x00"))[0].split("\x00").length-1;
}
This shim would need calling like so: location = lastIndexOf(array,nth_smallest);
const arr = [9,3,4,5,3,4,6,7,8,];
arr.sort((a,b)=>{return a-b});
console.log(arr[arr.length-1]);
arr.sort((a,b)=>{return a-b});
console.log(arr[0]);
to find lowest number or highest number in array first you need to sort any array then array will be short sequence after the sort any array always in index (arr[0]) will be lowest number in any array and (arr[arr.lenght-1]) always highest number because we sort in sequnece
thanks...
In Javascript is any other efficient way to achieve this task?
I tried as:
const a1 = [1,3,4,2,5,7,8,6];
var newArray =[];
function fun(a,n){
for(let i = 0; i<a.length; i++){
for(let j=i+1; j<a.length; j++){
if((a[i]+a[j])==n){
newArray.push([a[i],a[j]]);
}
}
}
}
fun(a1, 10)
console.log(newArray);
Here output:
[(3,7),(4,6),(2,8)]
The question is tagged javascript, but this answer is basically language agnostic.
If the array is sorted (or you can sort it), you can iterate over the array and for each element x in it binary search for (target-x) in the array. This gives you O(nlogn) run time.
If you can use extra memory, you can populate a dictionary with the elements of the array, and then for each element x in the array, look up the dictionary for (target-x). If your dictionary is implemented on a hashtable, this gives you O(n) run time.
I think your method makes sense from a brute force perspective.
In terms of optimization, a few things come to mind.
Do duplicates count? If not, you can remove all duplicates from
the starting lists.
You can sort the lists in ascending order,
and skip the remainder of the inner loop when the sum exceeds the
target value.
This is a general programming problem commonly referred to as the "two sum problem", which itself is a subset of the subset sum problem.
But nevertheless can be solved efficiently and I used this article as inspiration.
const a1 = [1, 3, 4, 2, 5, 7, 8, 6];
// our two sum function which will return
// all pairs in the array that sum up to S
function twoSum(arr, S) {
const sums = [];
const hashMap = new Map();
// check each element in array
for (let i = 0; i < arr.length; i++) {
// calculate S - current element
let sumMinusElement = S - arr[i];
// check if this number exists in hash map
// if so then we found a pair of numbers that sum to S
if (hashMap.has(sumMinusElement.toString())) {
sums.push([arr[i], sumMinusElement]);
}
// add the current number to the hash map
hashMap.set(arr[i].toString(), arr[i])
}
// return all pairs of integers that sum to S
return sums;
}
console.log(twoSum(a1, 10))
Here I use the Map object since I think it's faster when checking if number already exists, but I might be wrong and you can use just a plain object, as in the article, if you want.