How can I sort an indirect array with javascript?

假如想象 提交于 2020-06-07 04:51:17

问题


In my project, I need to sort an array that contain index of an other array (it's item). I've search for many hours, but I did not find anyone with my problem.

var arr = [1, 4, 3, 4, 5, 6, 7, 8, 9];
function sorting(){
    let arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8];
    //sorting code
}

Now, I want to sort arr2, so when I loop through it with this kind of code (under this paragraph), I access arr with the index in the sorted array (arr2).

  arr[arr2[i]]

My first move was to use arr2.sort(function(a,b){arr[a] - arr[b]}, but each time the sort wasn't good. I attempt to make my own sorting function, but my problem stayed.

To summarize, I want to sort arr2 so when I loop through it, I get the value of arr in ascending (or descending) order.

EDIT I fixe this problem, but another appears, when I applied the arr2 on my html, the order mess up.

    var arr = [1, 4, 3, 4, 5, 6, 7, 8, 9];
    function sorting(){
        let arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8];
        //The sorting block code (done)
        z = document.getElementsByClassName("triable"); //this is on what I applied arr2
        for (let i = 0; i < z.length; i++){
            z[i].style.order = arr2[i]; //this line work, but doesn't correctly do what I what it to do
        }
    }

For html, I have some div with a class "triable" and the code above this need to applied a css style (order) so the div visually change of position


回答1:


You need to return the delta. Otherwise the callback returns undefined for each call.

arr2.sort(function(a, b) {
    return arr[b] - arr[a];
});

For adding the right order, you need ot take the index from indices to address the right element and assign i as style order value.

function sort() {
    var array = [1, 4, 3, 4, 5, 6, 7, 8, 9],
        z = document.getElementsByClassName("triable");

    [...array.keys()]
        .sort((a, b) => array[b] - array[a])
        .forEach((v, i) => z[v].style.order = i);
}
<button onclick="sort()">sort</button><br>
<div style="display: flex;">
<span class="triable">1</span>
<span class="triable">4</span>
<span class="triable">3</span>
<span class="triable">4</span>
<span class="triable">5</span>
<span class="triable">6</span>
<span class="triable">7</span>
<span class="triable">8</span>
<span class="triable">9</span> 
</div>



回答2:


functional arbitrary sort

Here's another way to approach your problem. Let's say we have some fruits and an arbitrary order we wish to sort them in -

const fruits =
  //   0        1          2        3         4 
  [ "apple", "banana", "cherry", "orange", "peach" ]


const order =
  [ 1, 3, 2, 0, 4 ]

We want to be able to write something like this -

fruits.sort(sortByIndex(fruits, order))

console.log(fruits)
// [ "banana", "orange", "cherry", "apple", "peach" ]
//      1         3         2         0        4

We wish up a Comparison module to handle our sorting code -

const { empty, map } =
  Comparison

const sortByIndex = (values = [], indexes = []) =>
  map(empty, x => indexes.indexOf(values.indexOf(x)))

Now we just have to implement Comparison -

const Comparison =
  { empty: (a, b) =>
      a < b ? -1
        : a > b ? 1
          : 0
  , map: (m, f) =>
      (a, b) => m(f(a), f(b))
  }

const { empty, map } =
  Comparison

const sortByIndex = (values = [], indexes = []) =>
  map(empty, x => indexes.indexOf(values.indexOf(x)))

const fruits =
  [ "apple", "banana", "cherry", "orange", "peach" ]
  //   0        1          2        3         4 
  
const order =
  [ 1, 3, 2, 0, 4 ]

console.log(fruits)
// [ "apple", "banana", "cherry", "orange", "peach" ]

console.log(fruits.sort(sortByIndex(fruits, order)))
// [ "banana", "orange", "cherry", "apple", "peach" ]

why a module?

Implementing a Comparison module means we have a tidy place to store all of our comparison logic. We could easily implement other useful functions like reverse and concat now -

const Comparison =
  { // ...
  , concat: (m, n) =>
      (a, b) => Ordered.concat(m(a, b), n(a, b))
  , reverse: (m) =>
      (a, b) => m(b, a)
  }

const Ordered =
  { empty: 0
  , concat: (a, b) =>
      a === 0 ? b : a
  }

Now we can model complex sorting logic with ease -

const sortByName =
  map(empty, x => x.name)

const sortByAge =
  map(empty, x => x.age)

const data =
  [ { name: 'Alicia', age: 10 }
  , { name: 'Alice', age: 15 }
  , { name: 'Alice', age: 10 }
  , { name: 'Alice', age: 16 }
  ]

Sort by name then sort by age -

data.sort(concat(sortByName, sortByAge))
// [ { name: 'Alice', age: 10 }
// , { name: 'Alice', age: 15 }
// , { name: 'Alice', age: 16 }
// , { name: 'Alicia', age: 10 }
// ]

Sort by age then sort by name -

data.sort(concat(sortByAge, sortByName))
// [ { name: 'Alice', age: 10 }
// , { name: 'Alicia', age: 10 }
// , { name: 'Alice', age: 15 }
// , { name: 'Alice', age: 16 }
// ]

And effortlessly reverse any sorter. Here we sort by name then reverse sort by age -

data.sort(concat(sortByName, reverse(sortByAge)))
// [ { name: 'Alice', age: 16 }
// , { name: 'Alice', age: 15 }
// , { name: 'Alice', age: 10 }
// , { name: 'Alicia', age: 10 }
// ]

functional principles

Our Comparison module is flexible yet reliable. This allows us to write our sorters in a formula-like way -

// this...
concat(reverse(sortByName), reverse(sortByAge))

// is the same as...
reverse(concat(sortByName, sortByAge))

And similarly with concat expressions -

// this...
concat(sortByYear, concat(sortByMonth, sortByDay))

// is the same as...
concat(concat(sortByYear, sortByMonth), sortByDay)

// is the same as...
nsort(sortByYear, sortByMonth, sortByDay)

go nuts with nsort

Now let's say we want to sort by an arbitrary number of factors. For example, sorting date objects requires three comparisons: year, month, and day -

const { empty, map, reverse, nsort } =
  Comparison

const data =
  [ { year: 2020, month: 4, day: 5 }
  , { year: 2018, month: 1, day: 20 }
  , { year: 2019, month: 3, day: 14 }
  ]

const sortByDate =
  nsort
    ( map(empty, x => x.year)  // primary: sort by year
    , map(empty, x => x.month) // secondary: sort by month
    , map(empty, x => x.day)   // tertiary: sort by day
    )

Now we can sort by year, month, day -

data.sort(sortByDate)
// [ { year: 2019, month: 11, day: 14 }
// , { year: 2020, month: 4, day: 3 }
// , { year: 2020, month: 4, day: 5 }
// ]

And just as easily reverse sort by year, month, day -

data.sort(reverse(sortByDate))
// [ { year: 2020, month: 4, day: 5 }
// , { year: 2020, month: 4, day: 3 }
// , { year: 2019, month: 11, day: 14 }
// ]

Implementing N-sort is a breeze thanks to functional principles. Our concat and empty do all the hard work -

const Comparison =
  { // ...
  , nsort: (...m) =>
      m.reduce(Comparison.concat, Comparison.empty)
  }

Expand the snippet below to see this code in action -

const Comparison =
  { empty: (a, b) =>
      a < b ? -1
        : a > b ? 1
          : 0
  , map: (m, f) =>
      (a, b) => m(f(a), f(b))
  , concat: (m, n) =>
      (a, b) => Ordered.concat(m(a, b), n(a, b))
  , reverse: (m) =>
      (a, b) => m(b, a)
  , nsort: (...m) =>
      m.reduce(Comparison.concat, Comparison.empty)
  }

const Ordered =
  { empty: 0
  , concat: (a, b) =>
      a === 0 ? b : a
  }

const { empty, map, concat, reverse, nsort } =
  Comparison

const sortByDate =
  nsort
    ( map(empty, x => x.year)  // primary
    , map(empty, x => x.month) // secondary
    , map(empty, x => x.day)   // tertiary
    )

const data =
  [ { year: 2020, month: 4, day: 5 }
  , { year: 2019, month: 11, day: 14 }
  , { year: 2020, month: 4, day: 3 }
  ]

console.log(data.sort(reverse(sortByDate)))
// [ { year: 2020, month: 4, day: 5 }
// , { year: 2020, month: 4, day: 3 }
// , { year: 2019, month: 11, day: 14 }
// ]



回答3:


Much Code, but it works :)

For sort ASC:

var test = [1, 4, 3, 4, 5, 6, 7, 8, 9];
console.log("Original Array: " + test);
var len = test.length;
var indices = new Array(len);
for (var i = 0; i < len; ++i) indices[i] = i;
indices.sort(function (a, b) { return test[a] < test[b] ? -1 : test[a] > test[b] ? 1 : 0; });
test.sort();
console.log("Sort-ASC " + test);
console.log("Index from Array " + indices);

For sort DESC:

var test = [1, 4, 3, 4, 5, 6, 7, 8, 9];
console.log("Originales Array: " + test)
var len = test.length;
var indices = new Array(len);
for (var i = 0; i < len; ++i) indices[i] = i;
indices.sort(function (a, b) { return test[a] < test[b] ? -1 : test[a] > test[b] ? 1 : 0; });
indices.reverse();
test.sort();
test.reverse();
console.log("Sort-DESC " + test);
console.log("Index from Array " + indices);



回答4:


Its much easy buddy use this arr.sort(function(a, b){return a - b}); // use return otherwise it will not triggered and - + plus denote ascndng dcndng ordee Simple method ..... Happy coding



来源:https://stackoverflow.com/questions/61048153/how-can-i-sort-an-indirect-array-with-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!