Ranking array elements - javascript

I need an algorithm to rank elements of an array in Javascript.
Example : I have an array as follows:
[79, 5, 18, 5, 32, 1, 16, 1, 82, 13]
I need to rank the entries by value. So 82 should receive rank 1, 79 rank 2 etc.
If two entries have the same value they receive the same rank and the rank for a lower value is raised.
So for this array, the new ranking array would be:
[2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
How can I do this?

var arr = [79, 5, 18, 5, 32, 1, 16, 1, 82, 13];
var sorted = arr.slice().sort(function(a,b){return b-a})
var ranks = arr.map(function(v){ return sorted.indexOf(v)+1 });
console.log(ranks);
Result :
[2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
If you want to be compatible with old browsers, you may have to define a shim for indexOf and for map (note that if you want to do this very fast for very big arrays, you'd better use for loops and use an object as map instead of indexOf).

This won't work with older browsers because it uses ECMAScript 5 features, but it allows you to quickly and succinctly produce an array of rankings even for very large arrays. (It doesn't use indexOf which does a linear search and thus can be slow for large arrays.)
function cmp_rnum(a,b) {
// comparison function: reverse numeric order
return b-a;
}
function index_map(acc, item, index) {
// reduction function to produce a map of array items to their index
acc[item] = index;
return acc;
}
function ranks(v) {
var rankindex = v.slice().sort(cmp_rnum).reduceLeft(index_map, Object.create(null));
// reduceLeft() is used so the lowest rank wins if there are duplicates
// use reduce() if you want the highest rank
return v.map(function(item){ return rankindex[item]+1; });
}
Example output:
> ranks([79, 5, 18, 5, 32, 1, 16, 1, 82, 13]);
[2, 7, 4, 7, 3, 9, 5, 9, 1, 6]

function rank(arr, f) {
return arr
.map((x, i) => [x, i])
.sort((a, b) => f(a[0], b[0]))
.reduce((a, x, i, s) => (a[x[1]] =
i > 0 && f(s[i - 1][0], x[0]) === 0 ? a[s[i - 1][1]] : i + 1, a), []);
}
Usage:
rank([79, 5, 18, 5, 32, 1, 16, 1, 82, 13], (a, b) => b - a);
// [2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
Looks a bit ugly, but it doesn't use indexOf() or an object/map, so not only does it run a little faster, but more importantly, it respects the meaning of "same rankedness" as defined by the comparison function. If one uses indexOf() or an object, "same rankedness" can only mean a === b or String(a) === String(b).
Alternatively, use findIndex():
function rank(arr, f) {
const sorted = arr.slice().sort(f)
return arr.map(x => sorted.findIndex(s => f(x, s) === 0) + 1)
}

JavaScript ES6 simple two lines solution.
var arrayRankTransform = arr => {
const sorted = [...arr].sort((a, b) => b - a);
return arr.map((x) => sorted.indexOf(x) + 1);
};
console.log(arrayRankTransform([79, 5, 18, 5, 32, 1, 16, 1, 82, 13]));

I am not good at Javascript but in PHP it can be done quite easily the following way. Somebody good at JavaScript can come up with the relevant code.
$marks = [79, 5, 18, 5, 32, 1, 16, 1, 82, 13];
public function getRank($marks) {
$rank = 1; $count = 0; $ranks = [];
//sort the marks in the descending order
arsort($marks,1);
foreach($marks as $mark) {
//check if this mark is already ranked
if(array_key_exists($mark, $ranks)) {
//increase the count to keep how many times each value is repeated
$count++;
//no need to give rank - as it is already given
} else {
$ranks[$mark] = $i+$j;
$i++;
}
return $ranks;
}

I needed the same piece of code for an operations scheduling script I was writing. I used objects and their properties/keys, which can have any value and can be accessed whenever needed. Also, as far as I read in some articles, the search of properties in objects can be faster than search in arrays.
The script below has three simple steps:
sort the values (ascending or descending doesn't matter for the rest of the script)
find the ranks and number of occurrences for each value
replace the given values with ranks using the data from step 2
Note! The below script will not output duplicate ranks, but instead increments ranks for duplicate values/elements.
function rankArrayElements( toBeRanked ) {
// STEP 1
var toBeRankedSorted = toBeRanked.slice().sort( function( a,b ) { return b-a; } ); // sort descending
//var toBeRankedSorted = toBeRanked.slice().sort( function( a,b ) { return a-b; } ); // sort ascending
var ranks = {}; // each value from the input array will become a key here and have a rank assigned
var ranksCount = {}; // each value from the input array will become a key here and will count number of same elements
// STEP 2
for (var i = 0; i < toBeRankedSorted.length; i++) { // here we populate ranks and ranksCount
var currentValue = toBeRankedSorted[ i ].toString();
if ( toBeRankedSorted[ i ] != toBeRankedSorted[ i-1 ] ) ranks[ currentValue ] = i; // if the current value is the same as the previous one, then do not overwrite the rank that was originally assigned (in this way each unique value will have the lowest rank)
if ( ranksCount[ currentValue ] == undefined ) ranksCount[ currentValue ] = 1; // if this is the first time we iterate this value, then set count to 1
else ranksCount[ currentValue ]++; // else increment by one
}
var ranked = [];
// STEP 3
for (var i = toBeRanked.length - 1; i >= 0; i--) { // we need to iterate backwards because ranksCount starts with maximum values and decreases
var currentValue = toBeRanked[i].toString();
ranksCount[ currentValue ]--;
if ( ranksCount[ currentValue ] < 0 ) { // a check just in case but in theory it should never fail
console.error( "Negative rank count has been found which means something went wrong :(" );
return false;
}
ranked[ i ] = ranks[ currentValue ]; // start with the lowest rank for that value...
ranked[ i ] += ranksCount[ currentValue ]; // ...and then add the remaining number of duplicate values
}
return ranked;}
I also needed to do something else for my script.
The above output has the following meaning:
index - the ID of the element in the input array
value - the rank of the element from the input array
And I needed to basically 'swap the index with the value', so that I have a list of element IDs, arranged in the order of their ranks:
function convertRanksToListOfElementIDs( ranked ) { // elements with lower ranks will be first in the list
var list = [];
for (var rank = 0; rank < ranked.length; rank++) { // for each rank...
var rankFound = false;
for (var elementID = 0; elementID < ranked.length; elementID++) { // ...iterate the array...
if ( ranked[ elementID ] == rank ) { // ...and find the rank
if ( rankFound ) console.error( "Duplicate ranks found, rank = " + rank + ", elementID = " + elementID );
list[ rank ] = elementID;
rankFound = true;
}
}
if ( !rankFound ) console.error( "No rank found in ranked, rank = " + rank );
}
return list;}
And some examples:
ToBeRanked:
[36, 33, 6, 26, 6, 9, 27, 26, 19, 9]
[12, 12, 19, 22, 13, 13, 7, 6, 13, 5]
[30, 23, 10, 26, 18, 17, 20, 23, 18, 10]
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
[7, 7, 7, 7, 7, 2, 2, 2, 2, 2]
[2, 2, 2, 2, 2, 7, 7, 7, 7, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
rankArrayElements( ToBeRanked ):
[0, 1, 8, 3, 9, 6, 2, 4, 5, 7]
[5, 6, 1, 0, 2, 3, 7, 8, 4, 9]
[0, 2, 8, 1, 5, 7, 4, 3, 6, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
convertRanksToListOfElementIDs( rankArrayElements( ToBeRanked ) ):
[0, 1, 6, 3, 7, 8, 5, 9, 2, 4]
[3, 2, 4, 5, 8, 0, 1, 6, 7, 9]
[0, 3, 1, 7, 6, 4, 8, 5, 2, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

IMHO several solutions here are incorrect as they do not correctly handle values that occur after repeated values. Such followers should get the next rank. The highest rank should equal the number of unique values in the array. This solution (in PHP) is, IMHO, correct. Basically #Suresh's solution with the bugs removed.
function rank($marks){
$rank = 1; $ranks = [];
rsort($marks,SORT_NUMERIC);
foreach($marks as $mark) {
if(!isset($ranks[$mark])) {
$ranks[$mark] = $rank++;
}
}
return $ranks;
}

This should work with duplicate keys in the array
function rank(arry) {
let sorted = arry.slice().sort(function (a, b) {
return b - a
});
let currentRank = sorted.length;
let rankValue = null;
let ranks = [];
sorted.forEach(value => {
if(value !== rankValue && rankValue !==null) {
currentRank--;
}
ranks.push({value,currentRank});
rankValue = value;
});
let mapRanksToArrayValues = arry.map(function (x) {
let _rank = null;
ranks.forEach( rank => {
if(rank.value === x ) {
_rank = rank.currentRank;
return;
}
});
return _rank;
});
return mapRanksToArrayValues;
}

I created Rank_JS Pro.
<script>https://cdn.statically.io/gl/maurygta2/mquery/master/Rank Tools/rank.js</script>
Basics Methods:
var a = {
b: 2,
c: 7
}
Rank_Tools.rank(a,(pos,name,value) => {
return pos + ". "+name+" "+value;
})
// result
// rank1 = 1. c 7
// rank 2 = 2. b 2

This alternate way doesn't require the input array to be sorted:
// O(n^2)
const rank = (arr) => {
// Create a temporary array to keep metadata
// regarding each entry of the original array
const tmpArr = arr.map(v => ({
value: v,
rank: 1,
}));
// Get rid of douplicate values
const unique = new Set(arr);
// Loops through the set
for (let a of unique) {
for (let b of tmpArr) {
// increment the order of an element if a larger element is pressent
if (b.value < a) {
b.rank += 1;
}
}
}
// Strip out the unnecessary metadata
return tmpArr.map(v => v.rank);
};
console.log(rank([2600, 200, 36, 36, 400, 2, 0, 0]));
// => [1, 3, 4, 4, 2, 5, 6, 6]
console.log(rank([79, 5, 18, 5, 32, 1, 16, 1, 82, 13]));
// => [2, 7, 4, 7, 3, 8, 5, 8, 1, 6]

I had the same homework and this one works well, also it's easier to understand if you are new to this.
function rankings(arr) {
let rankingsArr = [];
for (let i = 0; i < arr.length; i++) {
var rank = 1;
for (let j = 0; j < arr.length; j++) {
if (arr[j] > arr[i]) rank++;
}
rankingsArr.push(rank);
}
return rankingsArr;
}

Related

How to divide array in different consecutive sequences

How to divide this array:- [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15] into two different arrays with one set of consecutive sequences in one array and another set of consecutive in another array.
for eg : array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15]
Desired output [0, 1, 2, 3, 4, 5, 6, 7, 8] and [12, 13, 14, 15]
The array should split into a number of consecutive sequences present in the array. If there are 3 consecutive sequences then the array should split into 3 different arrays with consecutive values and so on.
Another example = [1 ,2 ,3 ,4 5, 14, 15, 16, 22, 23, 24, 25]
Desired output [1, 2, 3, 4, 5] and [14, 15, 16] and [22, 23, 24, 25]
let arrnew = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15]
let arr2 = []
for (let j = 0; j < arrnew.length; j++) {
if (arrnew[j + 1] - 1 === arrnew[j]) {
arr2.push(arrnew[j])
}
}
Tried this but not working.
var arr = [1,2,3,4,6,7,8,9,10]
var result = []
for (var i = 0; i < arr.length; i++) {
if (i === 0) {
result.push([arr[0]])
} else if (arr[i] != arr[i-1] + 1) {
result.push([arr[i]])
} else {
tmp = result[result.length - 1]
tmp.push(arr[i])
result[result.length - 1] = tmp
}
}
console.log(result) // [ [ 1, 2, 3, 4 ], [ 6, 7, 8, 9, 10 ] ]
Here we loop through arr. For the first element, the only thing we need to do is append to result a new array with the first number.
Now, for every number after the first one, if the current number is not equal to the previous number + 1, we need to append a new array to result that contains the current number. Otherwise, we simply append the current number to the last array in result.
const arr = [1, 2, 3, 4, 5, 14, 15, 16, 22, 23, 24, 25];
const canSplit = (arr = []) => {
const count = arr.reduce((acc, num) => {
acc[num] = (acc[num] || 0) + 1
return acc
}, {})
const needed = {}
for (const num of arr) {
if (count[num] <= 0) {
continue
}
count[num] -= 1
if (needed[num] > 0) {
needed[num] -= 1
needed[num + 1] = (needed[num + 1] || 0) + 1
} else if (count[num + 1] > 0 && count[num + 2]) {
count[num + 1] -= 1
count[num + 2] -= 1
needed[num + 3] = (needed[num + 3] || 0) + 1
} else {
return false
}
}
return true
}
console.log(canSplit(arr));

return a new array of rankings of the original array

For example, if your input array is [10, 5, 20], the output should be [2, 3, 1], since 10 is the second largest number, 5 is the third largest, and 20 is the largest.
This is my function:
function rankings(arr){
const result=[];
let newArr=arr.sort((a,b)=>b-a);
for (let i=0;i<arr.length;i++){
for (let j=0;j<newArr.length;j++){
arr[i]===newArr[j]? result.push(j+1): console.log('');
}
}
return(result);
}
Using my function with this array [10,5,20] as my input, my output is [1,2,3] while
rankings([10, 5, 20]); // [2, 3, 1] expected output
rankings([6, 8, 1, 12, 4, 3, 9]); // [4, 3, 7, 1, 5, 6, 2] expected output
You can also try to sort the array, and then match the indexes of the original array.
Edited to cater the case of repeated numbers
var originalArray = [10, 5, 20, 10, 20]
, setArray = [...new Set(originalArray)]
, sortedArray = [...setArray].sort((a, b) => a - b)
, dataIndex = originalArray.map(d => sortedArray.indexOf(d) + 1)
console.log(dataIndex)
You could sort the values and filter the items for avoiding same values with different ranks.
function rankings(array) {
const sorted = [...array]
.sort((a, b) => b - a)
.filter((b, i, { [i - 1]: a }) => a !== b);
return array.map(v => sorted.indexOf(v) + 1);
}
console.log(rankings([10, 5, 20])); // [2, 3, 1]
console.log(rankings([6, 8, 1, 12, 4, 3, 9])); // [4, 3, 7, 1, 5, 6, 2]
console.log(rankings([10, 5, 20, 10, 20]));

Sort an Array after size but with multible identical values [duplicate]

I need an algorithm to rank elements of an array in Javascript.
Example : I have an array as follows:
[79, 5, 18, 5, 32, 1, 16, 1, 82, 13]
I need to rank the entries by value. So 82 should receive rank 1, 79 rank 2 etc.
If two entries have the same value they receive the same rank and the rank for a lower value is raised.
So for this array, the new ranking array would be:
[2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
How can I do this?
var arr = [79, 5, 18, 5, 32, 1, 16, 1, 82, 13];
var sorted = arr.slice().sort(function(a,b){return b-a})
var ranks = arr.map(function(v){ return sorted.indexOf(v)+1 });
console.log(ranks);
Result :
[2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
If you want to be compatible with old browsers, you may have to define a shim for indexOf and for map (note that if you want to do this very fast for very big arrays, you'd better use for loops and use an object as map instead of indexOf).
This won't work with older browsers because it uses ECMAScript 5 features, but it allows you to quickly and succinctly produce an array of rankings even for very large arrays. (It doesn't use indexOf which does a linear search and thus can be slow for large arrays.)
function cmp_rnum(a,b) {
// comparison function: reverse numeric order
return b-a;
}
function index_map(acc, item, index) {
// reduction function to produce a map of array items to their index
acc[item] = index;
return acc;
}
function ranks(v) {
var rankindex = v.slice().sort(cmp_rnum).reduceLeft(index_map, Object.create(null));
// reduceLeft() is used so the lowest rank wins if there are duplicates
// use reduce() if you want the highest rank
return v.map(function(item){ return rankindex[item]+1; });
}
Example output:
> ranks([79, 5, 18, 5, 32, 1, 16, 1, 82, 13]);
[2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
function rank(arr, f) {
return arr
.map((x, i) => [x, i])
.sort((a, b) => f(a[0], b[0]))
.reduce((a, x, i, s) => (a[x[1]] =
i > 0 && f(s[i - 1][0], x[0]) === 0 ? a[s[i - 1][1]] : i + 1, a), []);
}
Usage:
rank([79, 5, 18, 5, 32, 1, 16, 1, 82, 13], (a, b) => b - a);
// [2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
Looks a bit ugly, but it doesn't use indexOf() or an object/map, so not only does it run a little faster, but more importantly, it respects the meaning of "same rankedness" as defined by the comparison function. If one uses indexOf() or an object, "same rankedness" can only mean a === b or String(a) === String(b).
Alternatively, use findIndex():
function rank(arr, f) {
const sorted = arr.slice().sort(f)
return arr.map(x => sorted.findIndex(s => f(x, s) === 0) + 1)
}
JavaScript ES6 simple two lines solution.
var arrayRankTransform = arr => {
const sorted = [...arr].sort((a, b) => b - a);
return arr.map((x) => sorted.indexOf(x) + 1);
};
console.log(arrayRankTransform([79, 5, 18, 5, 32, 1, 16, 1, 82, 13]));
I am not good at Javascript but in PHP it can be done quite easily the following way. Somebody good at JavaScript can come up with the relevant code.
$marks = [79, 5, 18, 5, 32, 1, 16, 1, 82, 13];
public function getRank($marks) {
$rank = 1; $count = 0; $ranks = [];
//sort the marks in the descending order
arsort($marks,1);
foreach($marks as $mark) {
//check if this mark is already ranked
if(array_key_exists($mark, $ranks)) {
//increase the count to keep how many times each value is repeated
$count++;
//no need to give rank - as it is already given
} else {
$ranks[$mark] = $i+$j;
$i++;
}
return $ranks;
}
I needed the same piece of code for an operations scheduling script I was writing. I used objects and their properties/keys, which can have any value and can be accessed whenever needed. Also, as far as I read in some articles, the search of properties in objects can be faster than search in arrays.
The script below has three simple steps:
sort the values (ascending or descending doesn't matter for the rest of the script)
find the ranks and number of occurrences for each value
replace the given values with ranks using the data from step 2
Note! The below script will not output duplicate ranks, but instead increments ranks for duplicate values/elements.
function rankArrayElements( toBeRanked ) {
// STEP 1
var toBeRankedSorted = toBeRanked.slice().sort( function( a,b ) { return b-a; } ); // sort descending
//var toBeRankedSorted = toBeRanked.slice().sort( function( a,b ) { return a-b; } ); // sort ascending
var ranks = {}; // each value from the input array will become a key here and have a rank assigned
var ranksCount = {}; // each value from the input array will become a key here and will count number of same elements
// STEP 2
for (var i = 0; i < toBeRankedSorted.length; i++) { // here we populate ranks and ranksCount
var currentValue = toBeRankedSorted[ i ].toString();
if ( toBeRankedSorted[ i ] != toBeRankedSorted[ i-1 ] ) ranks[ currentValue ] = i; // if the current value is the same as the previous one, then do not overwrite the rank that was originally assigned (in this way each unique value will have the lowest rank)
if ( ranksCount[ currentValue ] == undefined ) ranksCount[ currentValue ] = 1; // if this is the first time we iterate this value, then set count to 1
else ranksCount[ currentValue ]++; // else increment by one
}
var ranked = [];
// STEP 3
for (var i = toBeRanked.length - 1; i >= 0; i--) { // we need to iterate backwards because ranksCount starts with maximum values and decreases
var currentValue = toBeRanked[i].toString();
ranksCount[ currentValue ]--;
if ( ranksCount[ currentValue ] < 0 ) { // a check just in case but in theory it should never fail
console.error( "Negative rank count has been found which means something went wrong :(" );
return false;
}
ranked[ i ] = ranks[ currentValue ]; // start with the lowest rank for that value...
ranked[ i ] += ranksCount[ currentValue ]; // ...and then add the remaining number of duplicate values
}
return ranked;}
I also needed to do something else for my script.
The above output has the following meaning:
index - the ID of the element in the input array
value - the rank of the element from the input array
And I needed to basically 'swap the index with the value', so that I have a list of element IDs, arranged in the order of their ranks:
function convertRanksToListOfElementIDs( ranked ) { // elements with lower ranks will be first in the list
var list = [];
for (var rank = 0; rank < ranked.length; rank++) { // for each rank...
var rankFound = false;
for (var elementID = 0; elementID < ranked.length; elementID++) { // ...iterate the array...
if ( ranked[ elementID ] == rank ) { // ...and find the rank
if ( rankFound ) console.error( "Duplicate ranks found, rank = " + rank + ", elementID = " + elementID );
list[ rank ] = elementID;
rankFound = true;
}
}
if ( !rankFound ) console.error( "No rank found in ranked, rank = " + rank );
}
return list;}
And some examples:
ToBeRanked:
[36, 33, 6, 26, 6, 9, 27, 26, 19, 9]
[12, 12, 19, 22, 13, 13, 7, 6, 13, 5]
[30, 23, 10, 26, 18, 17, 20, 23, 18, 10]
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
[7, 7, 7, 7, 7, 2, 2, 2, 2, 2]
[2, 2, 2, 2, 2, 7, 7, 7, 7, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
rankArrayElements( ToBeRanked ):
[0, 1, 8, 3, 9, 6, 2, 4, 5, 7]
[5, 6, 1, 0, 2, 3, 7, 8, 4, 9]
[0, 2, 8, 1, 5, 7, 4, 3, 6, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
convertRanksToListOfElementIDs( rankArrayElements( ToBeRanked ) ):
[0, 1, 6, 3, 7, 8, 5, 9, 2, 4]
[3, 2, 4, 5, 8, 0, 1, 6, 7, 9]
[0, 3, 1, 7, 6, 4, 8, 5, 2, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
IMHO several solutions here are incorrect as they do not correctly handle values that occur after repeated values. Such followers should get the next rank. The highest rank should equal the number of unique values in the array. This solution (in PHP) is, IMHO, correct. Basically #Suresh's solution with the bugs removed.
function rank($marks){
$rank = 1; $ranks = [];
rsort($marks,SORT_NUMERIC);
foreach($marks as $mark) {
if(!isset($ranks[$mark])) {
$ranks[$mark] = $rank++;
}
}
return $ranks;
}
This should work with duplicate keys in the array
function rank(arry) {
let sorted = arry.slice().sort(function (a, b) {
return b - a
});
let currentRank = sorted.length;
let rankValue = null;
let ranks = [];
sorted.forEach(value => {
if(value !== rankValue && rankValue !==null) {
currentRank--;
}
ranks.push({value,currentRank});
rankValue = value;
});
let mapRanksToArrayValues = arry.map(function (x) {
let _rank = null;
ranks.forEach( rank => {
if(rank.value === x ) {
_rank = rank.currentRank;
return;
}
});
return _rank;
});
return mapRanksToArrayValues;
}
I created Rank_JS Pro.
<script>https://cdn.statically.io/gl/maurygta2/mquery/master/Rank Tools/rank.js</script>
Basics Methods:
var a = {
b: 2,
c: 7
}
Rank_Tools.rank(a,(pos,name,value) => {
return pos + ". "+name+" "+value;
})
// result
// rank1 = 1. c 7
// rank 2 = 2. b 2
This alternate way doesn't require the input array to be sorted:
// O(n^2)
const rank = (arr) => {
// Create a temporary array to keep metadata
// regarding each entry of the original array
const tmpArr = arr.map(v => ({
value: v,
rank: 1,
}));
// Get rid of douplicate values
const unique = new Set(arr);
// Loops through the set
for (let a of unique) {
for (let b of tmpArr) {
// increment the order of an element if a larger element is pressent
if (b.value < a) {
b.rank += 1;
}
}
}
// Strip out the unnecessary metadata
return tmpArr.map(v => v.rank);
};
console.log(rank([2600, 200, 36, 36, 400, 2, 0, 0]));
// => [1, 3, 4, 4, 2, 5, 6, 6]
console.log(rank([79, 5, 18, 5, 32, 1, 16, 1, 82, 13]));
// => [2, 7, 4, 7, 3, 8, 5, 8, 1, 6]
I had the same homework and this one works well, also it's easier to understand if you are new to this.
function rankings(arr) {
let rankingsArr = [];
for (let i = 0; i < arr.length; i++) {
var rank = 1;
for (let j = 0; j < arr.length; j++) {
if (arr[j] > arr[i]) rank++;
}
rankingsArr.push(rank);
}
return rankingsArr;
}

How do I split an array into pairs into new arrays?

I'm trying to test my JS ability and i have no idea how to do the following.
I have an array of data var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];.
I want to pair the items and return a new array of arrays eg var newArray = [[1,2], [3,4], [5,6]]; ect
How would I got about this
var arr = [ 4, 1, 2, 8, 9, 0 ]
var newArray = []
for (var i=0; i<arr.length; i+=2) {
newArray.push([arr[i], arr[i+1]])
}
console.log(newArray)
I made a scalable function that you can use to do this for you but you can also configure it so that it is flexible enough to handle any number of objects that you want by passing in n.
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function partitionListByN(list, n = 2, reverse) {
if(reverse) {
return [list.splice(list.length - n).reverse()].concat(list.length > 0 partitionListByN(list, n, reverse) : list)
}
return [list.splice(0, n)].concat(list.length > 0 ? partitionListByN(list, n) : list)
}
console.log(partitionListByN(numbers, 3));
Whats happening is you pass in a list, we are returning a list [firstPartition, shortenedListFromRecursiveCall] so this will go [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] since I passed n in as 3. As you can see it defaults to 2 in the params list.
It also supports a reverse setting: console.log(partionListByN(numbers, 3, true)) this would yield [ [ 10, 9, 8 ], [ 7, 6, 5 ], [ 4, 3, 2 ], [ 1 ] ]
You could take a variable for the wanted chunk size and an index and iterate as long as some elements are available.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
size = 2,
chunks = [],
i = 0;
while (i < array.length) chunks.push(array.slice(i, i += size));
console.log(chunks);
.as-console-wrapper { max-height: 100% !important; top: 0; }

To create a one-dimensional array which contains, in order, the array indices used to access a number in the given variable

//I am trying to learn/understand to create a one-dimensional array which contains, in exact order, the array indices used to access a given number within a multi dimensional array
var multiDimensionalArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]];
// to access 15...
fifteen = multiDimensionalArray[3][3][3][3][2][0];
// Define the variable 'indexArray' here:
indexArray = fifteen.join();
//join method does not work for me. I have tried concat, slice, indexOf methods. Can't seem to be able to find the solution for this part. HELP!
// This will log your variables to the console
console.log(fifteen); //15
console.log(indexArray); //[3, 3, 3, 3, 2, 0]
You can use a recursive function :
var multiDimensionalArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]];
const getIndex = (arr, num) => {
const path = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
path.push(i);
path.push(getIndex(arr[i], num));
break;
}
if (arr[i] === num) {
path.push(i);
break;
}
}
return path.flat();
};
const indexArray = getIndex(multiDimensionalArray, 15);
console.log(indexArray);
Another approach with a recursive function:
var multiDimensionalArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]];
const find = (node, needle) => {
const index = node.indexOf(needle);
const nextIndex = node.findIndex(Array.isArray);
return [].concat(...
(index !== -1)
? [index]
: [nextIndex, find(node[nextIndex], needle)]
);
};
const result = find(multiDimensionalArray, 15);
console.log(result);
You could take a recursive approach and return either an empty array fro a not found value or the indices.
function getIndices(array, value) {
var subIndices = [],
index = array.findIndex(v => v === value || Array.isArray(v) && (subIndices = getIndices(v, value)).length);
return index === -1
? []
: [index, ...subIndices];
}
var array = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]]
console.log(getIndices(array, 15));
console.log(getIndices(array, 42));

Categories

Resources