Find second largest elements in array with duplicates in javascript - javascript

Am having array to find second largest elements including repeated value pls find below example.
const arr= [1,2,5,5,6]
expected result should be
[5,5]
I tried with map and math.max but i stuck up on logical issue.kindly help me

Below snippet could help you
const arr = [1, 2, 5, 5, 6]
const max = Math.max(...arr)
const newArr = arr.filter(element => element !== max)
const newMax = Math.max(...newArr)
const secondLargest = arr.filter(element => element === newMax)
console.log(secondLargest)

Here is a simpler approach, However it may not be the best approach in terms of performance for large data
const ar= [1,2,5,5,6]
secmax = Math.max(...ar.filter((n,i) => Math.max(...ar) !=n ))
res = ar.filter(n =>n == secmax)
console.log(res)

Using a Set to extract unique values shortens the code quite a bit
var arr = [1,5,2,5,4,8];
var uniqueValues = [...new Set(arr)].sort((a, b) => b-a);
var secondHighest = uniqueValues[1]; // 0 is max, 1 is second highest, etc.
var result = arr.filter(x => x === secondHighest);
Please keep in mind that there should be some due diligence in accessing the results (what happens if the code is fed with empty arrays, or arrays with a single repeated value? There are many cases not covered here)

You could group the values and sort the array of arrays and get the second array.
const
array = [1, 2, 5, 5, 6],
result = Object
.values(array.reduce((r, v) => (r[v] = [...(r[v] || []), v], r), {}))
.sort(([a], [b]) => b - a)
[1];
console.log(result);

Related

How to return array element whose first index is the largest number in JS?

Given the array below, how I can return the element whose first index contains the highest number:
let ar = [[1,24], [2, 6]]
I've tried many proposed solutions, but they return the number itself, while it should be, in the case above [2,6]
One of the solutions I've tried is, but it returns 24, 6:
var maxRow = arr.map(function(row){ return Math.max.apply(Math, row); });
To do what you require you can use reduce() to compare the values of the first item in each child array and return the one with the highest value:
let ar = [[1,24], [2, 6]]
let result = ar.reduce((acc, cur) => acc[0] < cur[0] ? cur : acc);
console.log(result);
One way is using a reduce. Try like this:
const ar = [
[1,24],
[2, 6],
];
const biggest = ar.reduce(
(acc, cur) => cur[0] > (acc?.[0] || 0) ? cur : acc,
[],
);
console.log(biggest);

Capture multiple values for ES6 array's map function

I want to perform an operation involving the current and the next array element.
For example, add current element with the next:
let arr = [0,1,2,3,4,5];
let newarr = arr.map((a,b) => a+b); //here, a and b are treated as the same element
expecting it to yield a new array of sums of current and next array element:
[0+1, 1+2, 2+3, 3+4, 4+5]
Is it possible to do that with map? If not, is there any other method that is suitable for manipulating multiple array elements in one operation?
here, a and b are treated as the same element
No. a is the value and b is the index. They happen to be the same in your particular data set.
Is it possible to do that with map?
Not with map itself. That will give you a new value for each value in the array, but you are starting with 6 values and ending up with 5, so you need an additional transformation.
Obviously you also need to use "the next value" instead of "the current index" too.
const arr = [0,1,2,3,4,5];
const newarr = arr.map((value, index, array) => value + array[index + 1]);
newarr.pop(); // Discard the last value (5 + undefined);
console.log(newarr);
You could slice the array and map with the value and value at same index of original array.
const
array = [0, 1, 2, 3, 4, 5],
result = array.slice(1).map((v, i) => array[i] + v);
console.log(result);
The second parameter in map is the index. Since map returns results for each iteration you can filter the unwanted item from the new array:
let arr = [0,1,2,3,4,5];
let newarr = arr.map((a,b) => a+arr[b+1]).filter(i => !isNaN(i));
console.log(newarr);
You can use reduce for that:
const arr = [0, 1, 2, 3, 4, 5];
const out = arr.reduce((acc, el, i) => {
if (i === arr.length - 1) { // don't do anything for the last element
return acc;
}
acc.push(el + arr[i + 1]);
return acc;
}, []);
console.log(out)
Using Array.prototype.slice(), Array.prototype.forEach().
const data = [0, 1, 2, 3, 4, 5],
numbers = data.slice(0, -1),
result = [];
numbers.forEach((number, index) => {
result.push(number + data[index + 1]);
});
console.log(result);

How to check if array element is the only one of its value in array?

I've seen many similar questions and answers here but none that directly answered this question. For each array element I'm looking for a way (with JavaScript) to check if it's the only one of its kind in the array, or if there is at least one other of it. For example:
const arr = [1,2,2]
looking for something that will return
true, false, false
when looping through arr.
const arr = [1, 2, 2];
console.log(arr.map(item => arr.indexOf(item) === arr.lastIndexOf(item)));
const arr = [1, 2, 2];
arr.map(item => arr.indexOf(item) === arr.lastIndexOf(item));
You can do it in two passes:
build a Map containing the count of each element
look up each element in that Map
Like so:
const getCounts = iterable => {
const counts = new Map();
for (const x of iterable) {
counts.set(x, (counts.get(x) ?? 0) + 1); // use || for ES6 compat
}
return counts;
};
const arrCounts = getCounts(arr);
arr.map(x => arrCounts.get(x) === 1)

Remove out nested array based on another array

I have this nested array
let arr = [['first', 'second'], ['third', 'fourth'], ['second', 'third']]
now I want to filter/remove based on exactly this array.
let filter = ['first', 'second']
and now my expected output should be:
[['third', 'fourth'], ['second', 'third']]
I only have this piece of code:
arr.filter(str => str.indexOf('second') === -1)
Which doesn't give the expected output, it also removed ['second', 'third'] because it filters whatever element that contains 'second'.. so they must be a better way or an improvement to the code.
If you care about ordering and need exact matches, you can write a simple arrays equal method and then filter out any equal arrays:
const arrEq = (a, b) => a.length === b.length && a.every((e, i) => b[i] === e);
const arr = [['first', 'second'], ['third', 'fourth'], ['second', 'third']];
const filter = ['first', 'second'];
console.log(arr.filter(e => !arrEq(e, filter)));
If you want the same elements but order doesn't matter:
const arrItemsEq = (a, b, cmp) => {
if (a.length !== b.length) {
return false;
}
a = a.slice().sort(cmp);
b = b.slice().sort(cmp);
return a.every((e, i) => e === b[i]);
};
const arr = [["a", "b"], ["b", "c"]];
const filter = ["b", "a"];
const strCmp = (x, y) => x.localeCompare(y);
console.log(arr.filter(e => !arrItemsEq(e, filter, strCmp)));
If you want to filter out arr elements if they don't include at least one of each filter element:
const arr = [["a", "b"], ["b", "c"]];
const filter = ["b", "a"];
console.log(arr.filter(x => !filter.every(y => x.includes(y))));
You need to test two arrays for equality. [There are many ways to do it] but once you pick one, you can simply remove any array that is equal to another. To avoid reimplementing the wheel, I'll use the LoDash _.isEqual for demonstration purposes:
let arr = [['first', 'second'], ['third', 'fourth']]
let filter = ['first', 'second']
let result = arr.filter(item => !_.isEqual(filter, item));
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
The equality function can be swapped to any implementation that satisfies you. A very simple one is simply:
function isEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
but it's not guaranteed to be correct (e.g, isEqual([1, 2], ["1,2"]) //true) and it's going to be slow with large inputs. But it might still work, depending on circumstances.
You can use filter to check if the element doesn't include every string of the filter array.
let arr = [['first', 'second'], ['third', 'fourth'], ['second', 'third']]
let filterout = ['first', 'second']
let arr2 = arr.filter(x => ! filterout.every(y => x.includes(y)))
console.log(arr2)
But by using filter it basically creates a new array with fewer elements. Which is good enough for a small array.
If if the goal is to directly change the original array, then those elements can be spliced from that array.
let arr = [ ['first', 'second'], ['third', 'fourth'], ['second', 'third'], ['second', 'first'] ]
let filterout = ['first', 'second']
// getting the indexes of the element that need to be removed
let idxArr = []
arr.forEach( (x, idx) => { if(x.every(y => filterout.includes(y))) idxArr.push(idx)})
// removing the elements from the array
idxArr.sort((i,j)=>j-i).forEach(idx => {arr.splice(idx, 1)})
console.log(arr)

Is there any method to find out which position my new number went to?

I have my array=[5,4,3,1] below, I want to .push(2), then .sort() my array and find out the new number's location in the array that I just pushed. I know the answer the new number's location is in array[1].
var array = [5,4,3,1];
array.push(2); //My new number
var sortedArray = arr.sort();
// sortedArray [1,2,3,4,5]
// The new number's position went to array[1]
Is there any method to find out which position my new number went to?
You could sort an array with indices and take the store index for serarching the inde fo the sorted array.
var array = [5, 4, 3, 1],
index = array.push(2) - 1,
indices = array
.map((_, i) => i)
.sort((a, b) => array[a] - array[b]);
console.log(index); // old index
console.log(indices.indexOf(index)); // new index
console.log(indices);
You can use findIndex.
const array = [5, 4, 3, 1];
const n = 32;
array.push(n);
const sortedArray = array.sort();
const index = sortedArray.findIndex(el => el === n);
console.log(sortedArray, index)
Note that you sort could be improved if you're using numbers and you want them to be in ascending order after the sort:
const sortedArray = array.sort((a, b) => b < a);
You can use reduce function.
This approach returns an array of indexes of number 2 if this is repeated.
In this case, will return an array with only one index.
Look at this code snippet
var array = [5,4,3,1];
array.push(2);
var indexes = array.sort().reduce((a, n, i) => {
if (n === 2) {
a.push(i);
}
return a;
}, []);
console.log(JSON.stringify(indexes));
See, returns an array with only one index.
Resource
Array.prototype.reduce()

Categories

Resources