Sorting an array in javascript: [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sort mixed alpha/numeric array
I'm trying to sort an array which contains elements in the form of xxx1, xxx2, xxx3. The Array.sort() method works fine until xxx9 and if there is an element by name xxx10 or xxx11, it fails. The order comes as xxx1, xxx10, xxx11, xxx2 and so on. Please let me know how to fix this.

You are seeing the results of natural string sorting. If string sort is not what you want, you should be using your own comparator.
Do something like:
arrayToBeSorted.sort(function(first,second)
{
/* some code that compares 'first' with 'second' and returns <0, ==0, >0*/
});

At the moment your array is being sorted alphabetically which is why you are getting those results. You need to provide your own comparator function to implement a numerical sort.
Try
var arr = ["xxx1","xxx10","xxx2","xxx20","xxx3","xxx30"];
var sortedArr = arr.sort( function( a, b ) {
// remove first 3 characters so remaining string will parse
a = parseInt( a.substr( 3 ) );
b = parseInt( b.substr( 3 ) );
return a - b;
});
console.log( sortedArr ); // => ["xxx1", "xxx2", "xxx3", "xxx10", "xxx20", "xxx30"]

You can implement custom sorting condition in callback to pass into Array.sort():
​var arr = [],
re = /^\D*(\d+)$/;
for(var i = 20; i-- > 0;) {
arr.push('xxx' + i);
}
function comparator(a, b) {
var numA = a.match(re)[1],
numB = b.match(re)[1];
return numA - numB;
}
arr.sort(comparator);
console.log(arr);
​
http://jsfiddle.net/f0t0n/qz62J/

Related

How to take array of numbers as input in Javascript? [duplicate]

This question already has answers here:
How to convert a string of numbers to an array of numbers?
(18 answers)
Closed 2 years ago.
"use strict";
let arr = readline().split(" "); // suppose inputs are 1 2 3 4 5
let res=0;
for(let i=0; i<arr.length; i++){
res += arr[i];
}
print(res); // output 012345
I know if I iterate through all the array elements and convert them to Number like arr[index] = Number(arr[index]); then I can get rid from this concatenation and will get pure sum.
But is there any way to convert all of these array elements of Strings to Number directly? without any iteration?
use Array.reduce:
let arr = readline().split(" "); // suppose inputs are 1 2 3 4 5
let res=arr.reduce((acc,e) => +e + acc,0);
"But is there any way to convert all of these array elements of Strings to Number directly?
Computationally, no. That's impossible. Iteration must happen. Otherwise it's like asking how you can visit every person on earth without having to travel.
But if you want to simplify your code by using functional programming then use Array.prototype.map:
const arrayOfInts = readLine().split( ' ' ).map( e => parseInt( e, 10 ) );
Take this further by performing sum with Array.prototype.reduce (also adding a filter to exclude NaN values which would break the summing operation):
I've documented the data-type of each chained function's return value on each line:
const sum = readLine() // string
.split( ' ' ) // string[]
.map( e => parseInt( e, 10 ) ) // ( number | NaN )[]
.filter( n => !isNaN( n ) ) // number[]
.reduce( ( acc, n ) => acc + n ); // number
You can not do it without iterating over it. However, you already loop through the array, so...
Just convert them in the loop where you add them:
"use strict";
let arr = readline().split(" "); // suppose inputs are 1 2 3 4 5
let res=0;
for(let i=0; i<arr.length; i++){
res += Number(arr[i]);
}
print(res); // output 15

Sort array by Criticality [duplicate]

This question already has answers here:
javascript sorting array based on another array
(1 answer)
Sort an array in the same order of another array
(4 answers)
Closed 3 years ago.
I have a criticality array and I want to sort by criticality, something like this:
let criticalityTypes = ['CRITICALITY_LOW', 'CRITICALITY_HIGH', 'CRITICALITY_MEDIUM'];
I get this order randomly, sometimes ** CRITICALITY_LOW ** comes in position 1 of the matrix ie either position 2, or 'CRITICALITY_MEDIUM' in 0 position,
What I want to do is order in the following order, regardless of the order that comes to me, sometimes I have just one criticality, or two:
['CRITICALITY_HIGH', 'CRITICALITY_MEDIUM', 'CRITICALITY_LOW'];
I tried to use sort function to order what I've done so far is this:
return criticalityTypes.sort((a, b) => {
if (a < b) return -1;
if (a > b) return 1;
});
But without success, any help?
You could take an object with the wanted order and sort by the delta of the values.
var criticalityTypes = ['CRITICALITY_LOW', 'CRITICALITY_HIGH', 'CRITICALITY_MEDIUM'],
order = { CRITICALITY_HIGH: 1, CRITICALITY_MEDIUM: 2, CRITICALITY_LOW: 3 };
criticalityTypes.sort((a, b) => order[a] - order[b]);
console.log(criticalityTypes);
Just another way:
let criticalityTypes = ['CRITICALITY_LOW', 'CRITICALITY_HIGH', 'CRITICALITY_MEDIUM'];
let orderedItems = [];
let desiredOrder = ['CRITICALITY_HIGH', 'CRITICALITY_MEDIUM', 'CRITICALITY_LOW'];
for (var i = 0; i < desiredOrder.length; i++) {
if (criticalityTypes.indexOf(desiredOrder[i]) > -1) {
orderedItems.push(desiredOrder[i]);
}
}
console.log(orderedItems);
The problem here is that you as the consumer of the api, do not have any clue what an "order" means for this items, as they are not "quantized", they are ideas, not an integer that you could call 'order' so you know what is what, the string is just for the display anyway.
Since you can not change the api, BUT they are always only these 3 and you always want them in the same order, you can mock your current call, put this as a 'placeholder' comparer so that you mock the calls to this function, until someones gives you something that you can use numericaly to determine an order, 'ascending' or 'descending' requires something quantized to have a meaning.
function criticalityTypes(a,b){
return ['CRITICALITY_HIGH', 'CRITICALITY_MEDIUM', 'CRITICALITY_LOW'];
}

Filtering arrays in JS [duplicate]

This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Closed 4 years ago.
I can't seem to figure this out.
I have two arrays. One of the arrays contains all the IDs of the other array, plus more.
var arr1 = [1,2,3,4,5]
var arr2 = [3,5]
My first array contains a lot more information which my second array does not (many other keys). I need to find a way to select all the elements of the first array that are present in the second array and return them so that I have just the elements of arr2 but with all the additional data in arr1. How can I do this?
EDIT: I should make it clear that in the first array, I am looking for specific IDs that match the indexes of the second array. So the solutions here are really good but not quite what I'm after. Example:
[ 0: { id: 1, name: "fred" } ...]
I want to match the id with my second array, not the index. Hope this makes sense!
I implemented a set data structure few months back, this is the difference function
function difference (firstarr,secondarr) {
let diffSet = [];
for ( let i = 0; i < secondarr.length ; i++ ) {
let hasValue = secondarr.includes(firstarr[i]);
if ( ! hasValue ) {
diffSet.push(secondarr[i]);
}
}
for ( let i = 0; i < firstarr.length ; i++ ) {
let hasValue = secondarr.includes(firstarr[i]);
if ( ! hasValue ) {
diffSet.push(firstarr[i]);
}
}
return diffSet;
};
console.log(difference([1,2,3,4],[3,4]));
Use filter and includes of Array.protitype.
var arr1 = [1,2,3,4,5]
var arr2 = [3,5,7]
console.log(arr1.filter(x=>!arr2.includes(x)));
arr2.forEach(function(x){
if(!arr1.includes(x)){
arr1.push(x);
}
})
console.log(arr1);

How can I iterate through a keyed array in JavaScript? [duplicate]

This question already has answers here:
Getting a list of associative array keys
(6 answers)
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 9 years ago.
I need to group the rows out of a table that has a matching order number, and then iterate over the groupings.
I have this code working which is creating the perfect array, data-wise:
var multItems = [];
// Combine items under orders,
$('tr.order').each(function(){
var orderNum = $(this).find('.ordernumber').val();
if ( ($('tr.order .ordernumber[value="' + orderNum + '"]').length > 1 ) && !(orderNum in multItems) ){
$('tr.order .ordernumber[value="' + orderNum + '"]').each(function(){
if (!(orderNum in multItems)){
multItems[orderNum] = [];
}
multItems[orderNum].push(this);
});
}
});
// Create new tr with order totals (of each item)
for (var i = multItems.length - 1; i >= 0; i--) {
// Code
};
But it creates an array with a length of 0, apparently, where multItems = [], but multItems[orderNumber] is defined... just with no way to access it if I don't know the order numbers.
I could make an array of the order numbers separately, but that feels like it must be the long way round. If I just create a numbered array, how do I know which number to pop the items from the orders into?
With your current code you have
var orderNum = $(this).find('.ordernumber').val();
where val() returns a string and not a number. So when you are doing multItems[orderNum] it is a string.
For the current code to work, you want to use a for in loop.
for (var prop in multItems) {
if( multItems.hasOwnProperty( prop ) ) {
console.log(multItems[prop]);
}
}
FYI: Order is not guaranteed. Also you should be using an object {} and not an array here.
Now the other thing you can do is to use parseInt to change the string into a number and than magically your for loop would start working. [This is assuming that ordernumber is a numeric value]
var orderNum = parseInt($(this).find('.ordernumber').val(), 10);

Sort array by key OR: Why is my for loop executing out of order?

I have an array of objects which I need placed in a certain order, depending on some configuration data. I am having a problem with itterating through the array in the proper order. I thought that if I made the array, and then stepped through with a for loop, I would be able to execute the code correctly. It is working great except in one use case, in which I add the fourth item to the array and then go back to the third.
links[0] = foo
links[1] = bar
links[2] = foobar
links[3] = a_herring
links[4] = a_shrubery
order = [] //loaded from JSON, works has the numbers 1 2 3 or 4 as values
//in this case:
order[0] = 1
order[1] = 2
order[2] = 4
order[3] = false
order[4] = 3
for(x in order){
if(order[x]){
printOrder[order[x]]=links[x]
//remember that in this case order[0] would
}
This should give me an array that looks like this:
//var printOrder[undefined,foo,bar,a_shrubbery,foobar]
But when I try to itterate through the array:
for(x in printOrder){
printOrder[x].link.appendChild(printOrder[x].image)
printOrder[x].appendChild(printOrder[x].link)
printOrder[x].appendChild(printOrder[x].text)
document.getElementById("myDiv").appendChild(printOrder[x]);
}
I get foo, bar, foobar, a_shrubbery as the output instead.
I need to either sort this array by key value, or step through it in the correct order.
Iterating over the numerically-index properties of Array instances should always be done with a numeric index:
for (var x = 0; x < printOrder.length; ++x) {
// whatever with printOrder[x]
}
Using the "for ... in" form of the statement won't get you predictable ordering, as you've seen, and it can have other weird effects too (particularly when you mix in JavaScript frameworks or tool libraries or whatever). It's used for iterating through the property names of an object, and it doesn't treat Array instances specially.
You need to create a function for finding values in an array like this:
Array.prototype.indexOf = function(value)
{
var i = this.length;
while ( i-- )
{
if ( this[ i ] == value ) return i;
}
return -1;
};
You can then use it like this:
//NOTICE: We're looping through LINKS not ORDER
for ( var i = 0; i < links.length; i++ )
{
var index = order.indexOf( i );
//It's in the order array
if ( index != -1 ) printOrder[ i ] = links[ i ];
}
REMEMBER: You need to make sure the values returned in json are integers. If they're strings, then you'll need to convert the integers to string when passed to indexOf.
The function you have in your question works as you suggest it should.
http://jsfiddle.net/NRP2D/8/ .
Clearly in this simplified case you have removed whatever error you are making in the real case.

Categories