简体   繁体   中英

What is the most efficient way to sort DOM elements based on values in an array of objects?

I have a series of divs that display data on different people. The data for each person is stored in an array of objects, and there are a lot of values for each person. There is a button for each property, and I would like to be able to sort the divs in ascending or descending order of a property by clicking on a button. Each div is given an id, that corresponds to an id of the associated person in the array.

The data looks like (but it is much larger than this):

people = [
   {
     id: 'xde234',
     height: '196',
     weight: '100',
     age: '34'
  },
  {
     id: 'sbd451',
     height: '176',
     weight: '140',
     age: '26'
  },
  {
     id: 'loe489',
     height: '156',
     weight: 'NA',
     age: '54'
  }]

The data for each person is displayed by looping through the data, creating a div for each person, assigning their id as the id of the div, and defining the inner html of a span with each property value. The class name of the span is the same as the property. So the HTML looks likes:

<div id="peopleContainer">
  <div id='xde234'>
     <span class="height">196</span>
     <span class="weight">100</span>
     <span class="age">34</span>
  </div>
  <div id='sbd451'>
     <span class="height">176</span>
     <span class="weight">140</span>
     <span class="age">26</span>
  </div>
  <div id='loe489'>
     <span class="height">156</span>
     <span class="weight">NA</span>
     <span class="age">54</span>
  </div>
</div>

Each button is created with an eventlistener eg:

heightButton = document.getElementById('heightButton')
heightButton.addEventListener('click', function(){
   // sortingFunction
}

I have been retrieving the divs and writing a sorting function using :

function sortingFunction(property){

   peopleContainer = document.getElementById('peopleContainer')
   allPeople =  peopleContainer.children
}

I have 3 questions really, the main one being the first:

  1. What is the most efficient way to sort and display this data in javascript for any property in the data, considering there will be many people and a large number of properties

  2. How do I implement ascending and descending sort into one button, so it alternates between the two.

  3. When a button is clicked, regardless of if it is ascending or descending, I would like all the NA values to be at the bottom, ie they are ignored in the sort but appended to the end.

Any help is greatly appreciated.

It may help to create a new data structure holding references to the DOM elements.

const peopleElements = {}
[...allPeople].forEach(node=>{
  peopleElements[node.id] = node;
});

Next you can sort your people array however you like. Once that's done, you can refresh the container:

people.forEach(person=>{
  const node = peopleElements[person.id];
  peopleContainer.append(node);
});

Note that appending an element that's already on the page will simply move it to the end. Moving each person to the end in turn will result in the elements appearing in sorted order.

thanks to @NiettheDarkAbsol his answer combined with the following sort functions has led me to a working answer. I use the data attribute to store the last type of sort (asc or desc). I use @NiettheDarkAbsol suggestion to append nodes, but do it twice, the second time with a condition to check for NAs, then move them to the bottom which works as desired. The sorting function now is :

function sortingFunction(e, property){

    peopleContainer = document.getElementById('peopleContainer');
    allPeople =  peopleContainer.children;

    const peopleElements = {};

    [...allPeople].forEach(node=>{
    peopleElements[node.id] = node;
    });
  
    if(e.target.getAttribute('data-lastSort') === 'desc'){
        e.target.setAttribute('data-lastSort','asc')
        people.sort(function(a,b){
            return a[property] - b[property]
        });
    }else{
        e.target.setAttribute('data-lastSort','desc')
        people.sort(function(a,b){
            return a[property] + b[property]
        });
    };
   
    people.forEach(person=>{
    const node = peopleElements[person.id];
    peopleContainer.append(node);
    };

    people.forEach(person=>{
       if(person[property] === 'NA'){
       const node = peopleElements[person.id];
       peopleContainer.append(node);
       };
    });

};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM