0

Apologies for the title, this is certainly a bit of a pretentious issue. I've got a range of numbers distributed across two arrays. These arrays hold the same dateset, however one has been converted to strings so that a reference key/tag can be assigned to each value indicating a category index.

const array1 = ["0:0", "0:5.476", "0:11.251", "0:31.916", "0:44.007", "0:53.911", "0:58.628", "0:65.729", "0:75.222", "0:88.849", "0:100", "1:0", "1:44.839", "1:60.303", "1:69.072", "1:73.150", "1:85.800", "1:100", "2:0", "2:11.796", "2:26.525", "2:81.782", "2:88.367", "2:100"]

0: 1: 2: represent the category index.

The second representation of the dateset is numeric and assigned to a separate array in ascending order.

const array2 = [0, 0, 0, 5.476, 11.251, 11.796, 26.525, 31.916, 44.007, 44.839, 53.911, 58.628, 60.303, 65.729, 69.072, 73.150, 75.222, 81.782, 85.800, 88.367, 88.849, 100, 100, 100]

The goal is to replicate the order of array2 in array1 whilst keeping the category index keys intact. As can be seen in the example below.

> console.log(array1);
["0:0", "1:0", "2:0", "0:5.476", "0:11.251", "2:11.796", "2:26.525", "0:31.916", "0:44.007", "1:44.839", "0:53.911", "0:58.628", "1:60.303", "0:65.729", "1:69.072", "1:73.150", "0:75.222", "2:81.782", "1:85.800", "2:88.367", "0:88.849", "0:100", "1:100", "2:100"]

Of course if I just wanted to match the order I could just un-string array1 and run it in ascending order. This example below un-strings all the 0: values.

let array1Ascend = [];
for(i=0;i<array1.length;i++){
    array1Ascent.push(Number(array1[i].match(/(?!0*:).*/)))
}
array1Ascent.sort(function(a, b) {
                return a - b;
            });

But the issue is that i'd of course lose the category index assignment of each value in doing that, which defeats the purpose. I'd say i'm more stuck on understanding the logic of this issue if anything. Any help would be appreciated, thank you.

srb633
  • 793
  • 3
  • 8
  • 16
  • 1
    I would correct the data structure of the first array, parsing the strings into something like `[{ cat: 0: value: 0 }, {cat: 0, value:5.476}, {cat:0, value:11.251}, ... ]`; then you'd be able to easily sort that array by the other array, then "restring" the data. See [How do I sort an array of objects based on the ordering of another array?](https://stackoverflow.com/q/9755889/215552) for the sorting bit. – Heretic Monkey May 29 '20 at 20:47
  • You're probably right. I tried nesting the values like that but ran into a couple walls alone the way so decided to try just dealing with strings. The index categories are not of any actual meaning to the dataset, they're just to be used as temporary reference for formatting the data. I'd be interested to a see an example if you've got a method for this. – srb633 May 29 '20 at 20:50

2 Answers2

2

Do you need to sort the array by element value ascendingly? You could provide your own sorting function to the Array.prototype.sort method.

const array1 = ["0:0", "0:5.476", "0:11.251", "0:31.916", "0:44.007", "0:53.911", "0:58.628", "0:65.729", "0:75.222", "0:88.849", "0:100", "1:0", "1:44.839", "1:60.303", "1:69.072", "1:73.150", "1:85.800", "1:100", "2:0", "2:11.796", "2:26.525", "2:81.782", "2:88.367", "2:100"];

console.log(
  array1.sort((a, b) => {
    const ai = parseFloat(a.split(':', 2)[1]);
    const bi = parseFloat(b.split(':', 2)[1]);
    if (ai === bi) {
      return 0;
    }
    
    return ai > bi ? 1 : -1;
  })
);
Typing
  • 128
  • 5
  • Btw does the `2` in `(':', 2)` represent the highest category index value or something else? – srb633 May 29 '20 at 21:15
  • 1
    Please see the MDN documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split – Typing Jun 01 '20 at 17:13
1

Here's what I would do. Probably more complicated than necessary, but it's just how my brain works. I use a few techniques that have been added to JavaScript in recent years, so feel free to ask about anything you don't understand.

const array1 = ["0:0", "0:5.476", "0:11.251", "0:31.916", "0:44.007", "0:53.911", "0:58.628", "0:65.729", "0:75.222", "0:88.849", "0:100", "1:0", "1:44.839", "1:60.303", "1:69.072", "1:73.150", "1:85.800", "1:100", "2:0", "2:11.796", "2:26.525", "2:81.782", "2:88.367", "2:100"];
const array2 = [0, 0, 0, 5.476, 11.251, 11.796, 26.525, 31.916, 44.007, 44.839, 53.911, 58.628, 60.303, 65.729, 69.072, 73.150, 75.222, 81.782, 85.800, 88.367, 88.849, 100, 100, 100];

const array3 = array1
  .map(val => { 
    // get the category index and value as numbers and properties of an object
    const [ cat, value ] = val.split(':').map(v => parseFloat(v)); 
    return { cat, value }; 
  })
  .sort((a,b) => 
    // sort by the index of the value in the second array
    array2.indexOf(a.value) - array2.indexOf(b.value)
  )
  // "restringify" the category index and value to a string
  .map(({cat, value}) => `${cat}:${value}`);

console.log(array3);
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • 1
    It was not clear from the question that the second array was just the values sorted numerically. This code will work irrespective of the order of the elements in the second array. – Heretic Monkey May 29 '20 at 21:07
  • Looks good, yeah I'm sure there are many cases where it won't be sorted numerically, in those situations it would be extra handy. Thank you – srb633 May 29 '20 at 21:12