Using Javascript to sort an array of numeric arrays - javascript

In Javascript, if I have an array of arrays, like the following:
X = [ [1,2,3,4],
[1,1,2,3],
[1,1,3],
[1,4],
[2,1,2],
[2,2]
]
Javascript sorts my array, comparing first entry first, then second, and so on, so that X.sort() returns the following:
[ [1,1,2,3],
[1,1,3],
[1,2,3,4],
[1,4],
[2,1,2],
[2,2]
]
Which is what I want. The problem is that the comparison operator for comparing the elements in the arrays is lexicographical, so [10,2] < [2,2], and, for example,
[[10,2],[1,1,3],[2,2]].sort() -> [[1,1,3],[10,2],[2,2]]
I need it to sort numerically, so that I get a sorted array of [[1,1,3],[2,2],[10,2]].
I tried using a comparison function of function(a,b){return (a-b) }, which would work for sorting an array of numbers, but this fails to properly sort my array, which makes sense (I think) because [10,2] - [1,1,3] yields NaN
How do I go about sorting an array of numeric arrays?

As I said in my comment, the sort function needs to account for the fact that it's receiving arrays as arguments and not plain values. So you need to handle them accordingly.
I suggest this;
var compFunc = function (a, b) {
var len = a.length > b.length ? b.length : a.length;
for(var i=0; i<len; ++i) {
if(a[i] - b[i] !== 0)
return a[i] - b[i];
}
return (a.length - b.length);
};
It first tries to look for differences in the common length of the two arrays. If the common length is exactly the same, then it sorts on the basis of array length. Here's a working fiddle.

What you want is to run a natural sort. For your compare function, replace it with the script mentioned in this article
http://my.opera.com/GreyWyvern/blog/show.dml/1671288

When you do X.sort(), Javascript is comparing your individual arrays as strings. It's basically doing a.toString().localeCompare(b.toString()). This is not what you want.
a.toString() is usually the same as a.join(',')
What I would do is compare each element in the arrays by using a for loop.
Something like this:
X.sort(function(a,b){
// Start off assuming values are equal
var ret = 0;
// Loop through a
for(var a_i = 0, a_length = a.length; a_i < a_length; a_i++){
// If b is shorter than a, it comes first
if(typeof b[a_i] === 'undefined'){
ret = 1;
break;
}
// if the element in a and b are *not* the same, then we can sort
else if(a[a_i] !== b[a_i]){
ret = a[a_i] - b[a_i];
break;
}
}
return ret;
});

You need to sort and compare between the 2 arrays:
http://jsfiddle.net/pXzB6/
var arr = [[10,2],[1,1,3],[2,2]];
arr.sort(function(a,b){
for(var i=0;i<a.length;i++){
var item_a = a[i];
for(var j=0;j<b.length;b++){
var item_b = b[j];
if(item_a == item_b){
continue;
}
else{
return item_a > item_b;
}
}
}
if(a.length == b.length){
return 0;
}
else{
return a.length > b.length;
}
});
console.log(arr);

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a-b});
then the result is :
1,5,10,25,40,100
This is simplest way i think, it's worked.

Related

How to find the match case using for loop in array

I have two arrays
var arr1 = [
{'id':'1','name':'test1','value':'star','role':['monitor']},
{'id':'2','name':'test2','value':'player','role':['monitor','Supervisor']},
{'id':'3','name':'test3','value':'saviour','role':['Supervisor']},
{'id':'4','name':'test4','value':'rock','role':['monitor']},
{'id':'5','name':'test5','value':'rocky','role':['boxer','monitor']}
]
var arr2 = ['Supervisor','monitor'];
I want to get the result where arr2 values is properly matched with arr1 roles values
Persons having both the category should be pushed to arr3.
So result should be {'id':'2','name':'test2','value':'player','role':['monitor','Supervisor']}.
if arr2 has one value then we can use arr1.indexOf(arr2[0])!='-1' but how to satisfy the "and" condition in the for loop..
I don't want to use this if possible, but it's all I can think of:
if( arr1.indexOf(arr2[0])!='-1' && arr1.indexOf(arr2[1])!='-1'){
return arr1[i];
}
Like #Marc B and #Terry say, you have just to do an intersection.
Here's a version without Jquery :
function intersection(a, b)
{
var result = [], ai = 0, bi = 0;
a.sort();
b.sort();
while( a.length > ai && b.length > bi )
{
if(a[ai] < b[bi] ){
ai++;
}
else if(a[ai] > b[bi] ){
bi++;
}
else
{
result.push(a[ai]);
ai++;
bi++;
}
}
return result;
}
var arr1 = [
{'id':'1','name':'test1','value':'star','role':['monitor']},
{'id':'2','name':'test2','value':'player','role':['monitor','Supervisor']},
{'id':'3','name':'test3','value':'saviour','role':['Supervisor']},
{'id':'4','name':'test4','value':'rock','role':['monitor']},
{'id':'5','name':'test5','value':'rocky','role':['boxer','monitor']}
]
var arr2 = ['Supervisor','monitor'];
var arr3 = [];
arr1.forEach(function(value){
if(intersection(value.role, arr2).length === arr2.length){
arr3.push(value);
}
});
console.log(arr3);
The main trick here is the equality of the arrays.
// Assuming we have array 'equals' method which compares the array equality
// el['role'] == arr2 won't work
var result = arr1.filter(function(el){
return el['role'].equals(arr2);
});
So, we can see that we only have to deal with array equality.
This post How to compare arrays in JavaScript? has a lot of discussion about it. Someone has even implemented 'equals' method.
You can use a jQuery one-liner to compare array—and the best thing is that they don't have to be in the exact same order. Simply use the .not() method, previously mentioned before.
The only trick is to use $.each() to loop through your first array, and compare the array of the role object against arr2 using .not():
var arr1 = [
{'id':'1','name':'test1','value':'star','role':['monitor']},
{'id':'2','name':'test2','value':'player','role':['monitor','Supervisor']},
{'id':'3','name':'test3','value':'saviour','role':['Supervisor']},
{'id':'4','name':'test4','value':'rock','role':['monitor']},
{'id':'5','name':'test5','value':'rocky','role':['boxer','monitor']}
]
var arr2 = ['Supervisor','monitor'];
var arr3 = [];
$.each(arr1, function(idx,person){
if($(person.role).not(arr2).length === 0 && $(arr2).not(person.role).length === 0) {
arr3.push(person);
}
});
console.log(arr3);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Compare 2 arrays and create a new one based on if exist [duplicate]

This question already has answers here:
What is the fastest or most elegant way to compute a set difference using Javascript arrays?
(14 answers)
Closed 8 years ago.
How can i compare this two arrays and create a new array (filtered) based on if any number in Array1 exist in Array2. Both arrays is dynamic and can have different lengths.
Array1 = 3796, 3831, 3858, 3860
Array2 = 3796, 4566, 2932, 3831, 3290, 3858, 4599, 3293 etc etc..
In this case i want my output to be:
Array3 = 4566, 2932, 3290, 4599, 3293
I assume you are comparing normal array. If no, you need to change for loop to for .. in loop.
function arr_diff(a1, a2)
{
var a=[], diff=[];
for(var i=0;i<a1.length;i++)
a[a1[i]]=true;
for(var i=0;i<a2.length;i++)
if(a[a2[i]]) delete a[a2[i]];
else a[a2[i]]=true;
for(var k in a)
diff.push(k);
return diff;
}
The function will return array having difference of the two arrays
This may be the shortest solution:
function diff(a, b) {
var c = [].slice.call(a.length > b.length ? a : b); // clone the longest array
return c.filter(function(c) { return a.indexOf(c) < 0 }); // filter out intersects
}
var a = [3796, 3831, 3858, 3860],
b = [3796, 4566, 2932, 3831, 3290, 3858, 4599, 3293];
console.log( diff(a, b) ); // [4566, 2932, 3290, 4599, 3293]
You can try this:
function in_array(needle, haystack){
for (var i = 0; i < haystack.length; i++){
if (needle == haystack[i]) return true;
}
return false;
}
for (var i = 0; i < array1.length; i++){
if (!in_array(array1[i], array2){
var index = array1.indexOf(array1[i]);
array1.splice(index, 1);
}
}
I have not tested it, but i guess it should work.

Sort array in ascending order while eleminating repeated values

I'm working on project where I have array simmilar to this
var sortBp = [ 'height58em', 'width480px', 'width768px', 'width959px', 'width767px', 'width767px' ];
I want to sort this array in ascending order while eleminating repeated values so that result should be
var sortBp = [ 'height58em', 'width480px', 'width767px', 'width768px', 'width959px' ];
I'm using following function to sort array in ascending array but how do I eliminate immediate values ?? (In above case 'width767px')
var sortBp = bpArrays.sort(function(a, b) {
a = a.replace(/[a-z]/g, '');
b = b.replace(/[a-z]/g, '');
return a - b;
});
Firstly, you can't eliminate elements while sorting. You have to sort the array first, then remove duplicates. Your solution using Array.prototype.filter and Array.prototype.indexOf might be good for unsorted array, but since your array is sorted, it's overhead here(takes O(n) for each). Instead you can just loop through the array and compare element with previous one.
function uniq(array) {
var i, l = array.length, result = [];
for (i = 0; i < l; i++) {
if (result[result.length - 1] != array[i]) {
result.push(array[i]);
}
}
return result;
}
This is same with Underscore and Prototype's uniq() implemention.
Last note: remember that this will work fine with sorted array only.
If this is not homework, i.e. you aren't required to implement the algorithm yourself, you could use a combination of sortBy and uniq functions.
sortBp = [ 'height58em', 'width480px', 'width768px', 'width959px', 'width767px', 'width767px' ];
_.uniq(_.sortBy(sortBp, function(x) {return x;}), true);
This returns:
["height58em", "width480px", "width767px", "width768px", "width959px"]
Note that this will be sort by lexical order, and if you do not wish this to happen, simply substitute the identity function function(x) {return x;} with your own logic.
Array.prototype.contains = function(k) {
for ( var p in this)
if (this[p] === k)
return true;
return false;
};
inputArray.sort();
function uniqueArray(inputArray){
result=[];
for(var i in inputArray){
if(!result.contains(inputArray[i])){
result.push(inputArray[i]);
}
}
return result;
}
Found It !!
var sortBp = [ 'height58em', 'width480px', 'width768px', 'width959px', 'width767px', 'width767px' ];
uniqueArray = sortBp.filter(function(elem, pos) {
return sortBp.indexOf(elem) == pos;
});
EDIT :
I have found another solution here : http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/
function eliminateDuplicates(arr) {
var i, len=arr.length, out=[], obj={};
for (i=0;i<len;i++) {
obj[arr[i]]=0;
}
for (i in obj) {
out.push(i);
}
return out;
}

Return index of greatest value in an array

I have this:
var arr = [0, 21, 22, 7];
What's the best way to return the index of the highest value into another variable?
This is probably the best way, since it’s reliable and works on old browsers:
function indexOfMax(arr) {
if (arr.length === 0) {
return -1;
}
var max = arr[0];
var maxIndex = 0;
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
maxIndex = i;
max = arr[i];
}
}
return maxIndex;
}
There’s also this one-liner:
let i = arr.indexOf(Math.max(...arr));
It performs twice as many comparisons as necessary and will throw a RangeError on large arrays, though. I’d stick to the function.
In one line and probably faster then arr.indexOf(Math.max.apply(Math, arr)):
var a = [0, 21, 22, 7];
var indexOfMaxValue = a.reduce((iMax, x, i, arr) => x > arr[iMax] ? i : iMax, 0);
document.write("indexOfMaxValue = " + indexOfMaxValue); // prints "indexOfMaxValue = 2"
Where:
iMax - the best index so far (the index of the max element so far, on the first iteration iMax = 0 because the second argument to reduce() is 0, we can't omit the second argument to reduce() in our case)
x - the currently tested element from the array
i - the currently tested index
arr - our array ([0, 21, 22, 7])
About the reduce() method (from "JavaScript: The Definitive Guide" by David Flanagan):
reduce() takes two arguments. The first is the function that performs the reduction operation. The task of this reduction function is to somehow combine or reduce two values into a single value, and to return that reduced value.
Functions used with reduce() are different than the functions used with forEach() and map(). The familiar value, index, and array values are passed as the second, third, and fourth arguments. The first argument is the accumulated result of the reduction so far. On the first call to the function, this first argument is the initial value you passed as the
second argument to reduce(). On subsequent calls, it is the value returned by the previous invocation of the function.
When you invoke reduce() with no initial value, it uses the first element of the array as the initial value. This means that the first call to the reduction function will have the first and second array elements as its
first and second arguments.
Another solution of max using reduce:
[1,2,5,0,4].reduce((a,b,i) => a[0] < b ? [b,i] : a, [Number.MIN_VALUE,-1])
//[5,2]
This returns [5e-324, -1] if the array is empty. If you want just the index, put [1] after.
Min via (Change to > and MAX_VALUE):
[1,2,5,0,4].reduce((a,b,i) => a[0] > b ? [b,i] : a, [Number.MAX_VALUE,-1])
//[0, 3]
To complete the work of #VFDan, I benchmarked the 3 methods: the accepted one (custom loop), reduce, and find(max(arr)) on an array of 10000 floats.
Results on chromimum 85 linux (higher is better):
custom loop: 100%
reduce: 94.36%
indexOf(max): 70%
Results on firefox 80 linux (higher is better):
custom loop: 100%
reduce: 96.39%
indexOf(max): 31.16%
Conclusion:
If you need your code to run fast, don't use indexOf(max).
reduce is ok but use the custom loop if you need the best performances.
You can run this benchmark on other browser using this link:
https://jsben.ch/wkd4c
If you are utilizing underscore, you can use this nice short one-liner:
_.indexOf(arr, _.max(arr))
It will first find the value of the largest item in the array, in this case 22. Then it will return the index of where 22 is within the array, in this case 2.
Unless I'm mistaken, I'd say it's to write your own function.
function findIndexOfGreatest(array) {
var greatest;
var indexOfGreatest;
for (var i = 0; i < array.length; i++) {
if (!greatest || array[i] > greatest) {
greatest = array[i];
indexOfGreatest = i;
}
}
return indexOfGreatest;
}
var arr=[0,6,7,7,7];
var largest=[0];
//find the largest num;
for(var i=0;i<arr.length;i++){
var comp=(arr[i]-largest[0])>0;
if(comp){
largest =[];
largest.push(arr[i]);
}
}
alert(largest )//7
//find the index of 'arr'
var arrIndex=[];
for(var i=0;i<arr.length;i++){
var comp=arr[i]-largest[0]==0;
if(comp){
arrIndex.push(i);
}
}
alert(arrIndex);//[2,3,4]
EDIT: Years ago I gave an answer to this that was gross, too specific, and too complicated. So I'm editing it. I favor the functional answers above for their neat factor but not their readability; but if I were more familiar with javascript then I might like them for that, too.
Pseudo code:
Track index that contains largest value. Assume index 0 is largest initially. Compare against current index. Update index with largest value if necessary.
Code:
var mountains = [3, 1, 5, 9, 4];
function largestIndex(array){
var counter = 1;
var max = 0;
for(counter; counter < array.length; counter++){
if(array[max] < array[counter]){
max = counter;
}
}
return max;
}
console.log("index with largest value is: " +largestIndex(mountains));
// index with largest value is: 3
function findIndicesOf(haystack, needle)
{
var indices = [];
var j = 0;
for (var i = 0; i < haystack.length; ++i) {
if (haystack[i] == needle)
indices[j++] = i;
}
return indices;
}
pass array to haystack and Math.max(...array) to needle. This will give all max elements of the array, and it is more extensible (for example, you also need to find min values)
If you create a copy of the array and sort it descending, the first element of the copy will be the largest. Than you can find its index in the original array.
var sorted = [...arr].sort((a,b) => b - a)
arr.indexOf(sorted[0])
Time complexity is O(n) for the copy, O(n*log(n)) for sorting and O(n) for the indexOf.
If you need to do it faster, Ry's answer is O(n).
A minor modification revised from the "reduce" version of #traxium 's solution taking the empty array into consideration:
function indexOfMaxElement(array) {
return array.reduce((iMax, x, i, arr) =>
arr[iMax] === undefined ? i :
x > arr[iMax] ? i : iMax
, -1 // return -1 if empty
);
}
A stable version of this function looks like this:
// not defined for empty array
function max_index(elements) {
var i = 1;
var mi = 0;
while (i < elements.length) {
if (!(elements[i] < elements[mi]))
mi = i;
i += 1;
}
return mi;
}
To find the index of the greatest value in an array, copy the original array into the new array and then sort the original array in decreasing order to get the output [22, 21, 7, 0]; now find the value 22 index in the copyNumbers array using this code copyNumbers.indexOf(numbers[0]);
<script>
const numbers = [0, 21, 22, 7];
const copyNumbers = [];
copyNumbers.push(...numbers);
numbers.sort(function(a, b){
return b - a
});
const index = copyNumbers.indexOf(numbers[0]);
console.log(index);
</script>
Make this
const max = arr.reduce((m, n) => Math.max(m, n)), then the indexes of the max
get index with findIndex
var index = arr.findIndex(i => i === max)

Max value in array, based on a function

I have an array of objects. I want to find the "maximum" of this array based on a function that returns whichever object is bigger when given 2 objects.
function comparison(first, second) {
// ... arbitrary comparison based on properties...
return first; // or second
}
var a = [obj1, obj2, obj3];
var maxObj = ????(comparison);
What do I fill in here? What's elegant and short?
Something like this should be quicker than sort (depending on the data):
/*
values: array of values to test.
fn: function that takes two arguements and returns true if the first is bigger.
*/
var maximum = function(values, fn) {
var currentValue, maxValue = values.pop();
while(values.length)
maxValue = fn(maxValue, currentValue = values.pop()) ? maxValue : currentValue;
return maxValue;
}
Examples: http://jsfiddle.net/SaBJ4/2/
Even better, use Array.reduce:
var a = ['abc', 'defg', 'highlkasd', 'ac', 'asdh'];
a.reduce(function(a, b) { return a.length > b.length ? a : b; }); // highlkasd
What's wrong with the obvious approach?
for(var i = 0, max; i < a.length; ++i)
max = typeof max == 'undefined' ? a[i] : comparison(a[i], max);
Wrap that up however you like.
Or you can take advantage of the fact that a = []; x = a[0] leaves you with undefined in x and do it RobG's way:
for(var i = 1, max = a[0]; i < a.length; ++i)
max = comparison(a[i], max);
That nicely avoids a bunch of typeof operators and comparisons that you really don't need.
[obj,obj,obj].sort(comparison)
// aka
var sorted = [obj,obj,obj].sort(function(a,b){
// return 1/0/-1
});
Then either pop the top or bottom element off (however you're sorting) to get the "max" object.
Array.Sort

Categories