คุณจัดเรียงอาร์เรย์ในหลายคอลัมน์ได้อย่างไร?


121

ฉันมีอาร์เรย์หลายมิติ อาร์เรย์หลักคืออาร์เรย์ของ

[publicationID][publication_name][ownderID][owner_name] 

สิ่งที่ฉันพยายามที่จะทำคือการจัดเรียงอาร์เรย์โดยแล้วโดยowner_name publication_nameฉันรู้ว่าใน JavaScript คุณมีArray.sort()ซึ่งคุณสามารถใส่ฟังก์ชันที่กำหนดเองได้ในกรณีของฉันฉันมี:

function mysortfunction(a, b) {
    var x = a[3].toLowerCase();
    var y = b[3].toLowerCase();

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

นี่คือการปรับเพียงการเรียงลำดับในคอลัมน์หนึ่งคือ OWNER_NAME แต่ฉันจะปรับเปลี่ยนการจัดเรียงบนowner_nameแล้วpublication_name?

คำตอบ:


169

หากชื่อเจ้าของต่างกันให้จัดเรียงตามชื่อ มิฉะนั้นให้ใช้ชื่อสิ่งพิมพ์สำหรับ tiebreaker

function mysortfunction(a, b) {

  var o1 = a[3].toLowerCase();
  var o2 = b[3].toLowerCase();

  var p1 = a[1].toLowerCase();
  var p2 = b[1].toLowerCase();

  if (o1 < o2) return -1;
  if (o1 > o2) return 1;
  if (p1 < p2) return -1;
  if (p1 > p2) return 1;
  return 0;
}

@dcp ฉันไม่เห็นว่ามันสามารถจัดเรียงแอตทริบิวต์ที่สองได้อย่างไร เว้นแต่คุณจะวนซ้ำให้มากที่สุดเท่าจำนวนคอลัมน์ที่เลือก .. ฉันใช่ไหม? เช่น[[A, 10], [J, 15], [A, 5], [J, 5]] => [[A, 10], [A, 5], [J, 15], [J, 5]]
ลา ...

2
@ user26409021 - ไม่ถูกต้อง มันจะลงเอยด้วย [[A, 5], [A, 10], [J, 5], [J, 15]] โดยจัดเรียงตามแอตทริบิวต์แรกก่อนและหากเหมือนกันก็จะจัดเรียงตามแอตทริบิวต์ที่สอง ดังนั้นในตัวอย่างของคุณ A จะมาก่อน J ในกรณีที่ A เหมือนกันสำหรับสององค์ประกอบก็จะใช้แอตทริบิวต์ที่สอง ดังนั้นสำหรับ [A, 10], [A, 5], 5 มาก่อน 10 ดังนั้นจึงลงเอยด้วย [A, 5], [A, 10] สำหรับลำดับ สิ่งที่คุณอาจขาดหายไปคือ mysortfunction ถูกเรียกหลายครั้งเมื่อคุณใช้ Array.sort จนกว่าการเรียงลำดับจะเสร็จสิ้น
dcp

3
@ user26409021 - ไม่จำเป็นต้องมีการวนซ้ำในฟังก์ชัน mysortfunction เนื่องจาก Array.sort จะเรียกใช้ฟังก์ชันตามต้องการจนกว่า Array จะเรียงลำดับอย่างถูกต้อง สิ่งเดียวที่ mysortfunction รับผิดชอบคือการพิจารณาว่าอาร์กิวเมนต์ a และ b เท่ากันไม่ว่า a น้อยกว่า b หรือ a มากกว่า b หรือไม่ เราไม่จำเป็นต้องวนซ้ำเพื่อทำการตัดสินใจนั้น หวังว่าจะช่วยได้
dcp

58

ฉันคิดว่าสิ่งที่คุณกำลังมองหาก็คือ By.js: https://github.com/Teun/thenBy.js

อนุญาตให้คุณใช้ Array.sort มาตรฐาน แต่มีfirstBy().thenBy().thenBy()สไตล์

ตัวอย่างที่สามารถมองเห็นได้ที่นี่


ระมัดระวังประสิทธิภาพของชุดข้อมูลขนาดใหญ่ ทุกครั้งที่thenByเรียกรายการอาร์เรย์ทั้งหมดจะวนซ้ำอีกครั้ง
Ray Shan

6
นั่นไม่ใช่อย่างนั้นแน่นอน เมื่อคุณเรียก thenBy () จะสร้างฟังก์ชันใหม่ที่ห่อหุ้มฟังก์ชันก่อนหน้านี้ ในเวลาจัดเรียง javascript จะไม่ "วนซ้ำ" รายการอย่างเคร่งครัด แต่จะเรียกใช้ฟังก์ชันที่คุณส่งผ่านหลายครั้ง จำนวนการโทรจะไม่เปลี่ยนแปลงโดยใช้ thenBy สำหรับการพิจารณาประสิทธิภาพบางประการโปรดอ่าน: github.com/Teun/thenBy.js#a-word-on-performance
Teun D

2
ฉันเข้าใจว่าฉันพูดไม่ถูกขอบคุณที่นึกถึงประสิทธิภาพ อาจเพิ่มหมายเหตุเกี่ยวกับข้อควรพิจารณาเกี่ยวกับหน่วยความจำในการสร้างการปิดด้วยฟังก์ชันใหม่
Ray Shan

จะใช้สิ่งนี้สำหรับไดนามิคหลายตัวได้อย่างไร? หรือวนซ้ำ?
Hemil Patel

@ แฮรี่ถ้าคุณไม่สามารถใช้งานได้โปรดโพสต์ปัญหาเกี่ยวกับตัวอย่างที่คุณไม่สามารถจัดเรียงได้เพื่อให้คนอื่นได้เรียนรู้ด้วย ยินดีที่จะช่วยเหลือคุณ github.com/Teun/thenBy.js/issues
Teun D

35

วิธีที่ดีในการจัดเรียงในหลายสาขาที่มีสตริงคือการใช้และผู้ประกอบการบูลีนtoLocaleCompare||

สิ่งที่ต้องการ:

// Sorting record releases by name and then by title.
releases.sort((oldRelease, newRelease) => {
  const compareName = oldRelease.name.localeCompare(newRelease.name);
  const compareTitle = oldRelease.title.localeCompare(newRelease.title);

  return compareName || compareTitle;
})

หากคุณต้องการจัดเรียงในเขตข้อมูลเพิ่มเติมคุณสามารถเชื่อมโยงพวกเขาออกจากคำสั่งส่งคืนด้วยตัวดำเนินการบูลีนเพิ่มเติม


ตามความเป็นจริงคุณสามารถจัดระเบียบได้ด้วย a.reduce()
ekkis

อย่างไรก็ตาม.localCompare()ส่งกลับค่า -1, 0, 1 ดังนั้นฉันไม่คิดว่าโซลูชันของคุณจะทำงานเป็น || เหมาะสำหรับบูลีน
ekkis

10
@ekkis ทั้ง 1 และ -1 เป็น "ความจริง" ดังนั้นนี่จึงเป็นคำตอบที่สวยงามมาก ฉันเพิ่งทำสิ่งนี้ไป sortItems = (a, b) => (a.distance - b.distance) || (a.name - b.name); และมันก็เป็นเสน่ห์สำหรับความต้องการที่ไม่จู้จี้จุกจิกของฉัน
60

1
@bstst ทางของคุณดีกว่าเพราะไม่ได้ประเมิน(a.name - b.name)ถ้าจำเป็น การสร้างตัวแปรก่อนจะทำงานพิเศษแม้ว่าจะไม่จำเป็นก็ตาม
andi

นั่นเป็นความจริงสิ่งนี้ได้ผลเกินความจำเป็น แต่ฉันจะเปลี่ยนเฉพาะในส่วนที่สำคัญเท่านั้น สำหรับโค้ดที่จัดเรียงข้อมูลจำนวนเล็กน้อยความชัดเจนของโค้ดจะสำคัญกว่าความสมบูรณ์แบบ
tbranyen

27

พบความจำเป็นในการสร้างอาร์เรย์อ็อบเจ็กต์ asc และ desc แบบผสม SQL ตามคีย์

วิธีแก้ปัญหาของ kennebec ข้างต้นช่วยให้ฉันไปถึงสิ่งนี้:

Array.prototype.keySort = function(keys) {

keys = keys || {};

// via
// /programming/5223/length-of-javascript-object-ie-associative-array
var obLen = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key))
            size++;
    }
    return size;
};

// avoiding using Object.keys because I guess did it have IE8 issues?
// else var obIx = function(obj, ix){ return Object.keys(obj)[ix]; } or
// whatever
var obIx = function(obj, ix) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (size == ix)
                return key;
            size++;
        }
    }
    return false;
};

var keySort = function(a, b, d) {
    d = d !== null ? d : 1;
    // a = a.toLowerCase(); // this breaks numbers
    // b = b.toLowerCase();
    if (a == b)
        return 0;
    return a > b ? 1 * d : -1 * d;
};

var KL = obLen(keys);

if (!KL)
    return this.sort(keySort);

for ( var k in keys) {
    // asc unless desc or skip
    keys[k] = 
            keys[k] == 'desc' || keys[k] == -1  ? -1 
          : (keys[k] == 'skip' || keys[k] === 0 ? 0 
          : 1);
}

this.sort(function(a, b) {
    var sorted = 0, ix = 0;

    while (sorted === 0 && ix < KL) {
        var k = obIx(keys, ix);
        if (k) {
            var dir = keys[k];
            sorted = keySort(a[k], b[k], dir);
            ix++;
        }
    }
    return sorted;
});
return this;
};

ตัวอย่างการใช้งาน:

var obja = [
  {USER:"bob",  SCORE:2000, TIME:32,    AGE:16, COUNTRY:"US"},
  {USER:"jane", SCORE:4000, TIME:35,    AGE:16, COUNTRY:"DE"},
  {USER:"tim",  SCORE:1000, TIME:30,    AGE:17, COUNTRY:"UK"},
  {USER:"mary", SCORE:1500, TIME:31,    AGE:19, COUNTRY:"PL"},
  {USER:"joe",  SCORE:2500, TIME:33,    AGE:18, COUNTRY:"US"},
  {USER:"sally",    SCORE:2000, TIME:30,    AGE:16, COUNTRY:"CA"},
  {USER:"yuri", SCORE:3000, TIME:34,    AGE:19, COUNTRY:"RU"},
  {USER:"anita",    SCORE:2500, TIME:32,    AGE:17, COUNTRY:"LV"},
  {USER:"mark", SCORE:2000, TIME:30,    AGE:18, COUNTRY:"DE"},
  {USER:"amy",  SCORE:1500, TIME:29,    AGE:19, COUNTRY:"UK"}
];

var sorto = {
  SCORE:"desc",TIME:"asc", AGE:"asc"
};

obja.keySort(sorto);

ให้ผลดังต่อไปนี้:

 0: {     USER: jane;     SCORE: 4000;    TIME: 35;       AGE: 16;    COUNTRY: DE;   }
 1: {     USER: yuri;     SCORE: 3000;    TIME: 34;       AGE: 19;    COUNTRY: RU;   }
 2: {     USER: anita;    SCORE: 2500;    TIME: 32;       AGE: 17;    COUNTRY: LV;   }
 3: {     USER: joe;      SCORE: 2500;    TIME: 33;       AGE: 18;    COUNTRY: US;   }
 4: {     USER: sally;    SCORE: 2000;    TIME: 30;       AGE: 16;    COUNTRY: CA;   }
 5: {     USER: mark;     SCORE: 2000;    TIME: 30;       AGE: 18;    COUNTRY: DE;   }
 6: {     USER: bob;      SCORE: 2000;    TIME: 32;       AGE: 16;    COUNTRY: US;   }
 7: {     USER: amy;      SCORE: 1500;    TIME: 29;       AGE: 19;    COUNTRY: UK;   }
 8: {     USER: mary;     SCORE: 1500;    TIME: 31;       AGE: 19;    COUNTRY: PL;   }
 9: {     USER: tim;      SCORE: 1000;    TIME: 30;       AGE: 17;    COUNTRY: UK;   }
 keySort: {  }

(โดยใช้ฟังก์ชันการพิมพ์จากที่นี่ )

นี่เป็นตัวอย่างที่ jsbin

แก้ไข: ทำความสะอาดและโพสต์เป็น mksort.js บน GitHub


17

สิ่งนี้มีประโยชน์สำหรับอัลฟ่าทุกขนาด ส่งดัชนีที่คุณต้องการจัดเรียงตามลำดับเป็นอาร์กิวเมนต์

Array.prototype.deepSortAlpha= function(){
    var itm, L=arguments.length, order=arguments;

    var alphaSort= function(a, b){
        a= a.toLowerCase();
        b= b.toLowerCase();
        if(a== b) return 0;
        return a> b? 1:-1;
    }
    if(!L) return this.sort(alphaSort);

    this.sort(function(a, b){
        var tem= 0,  indx=0;
        while(tem==0 && indx<L){
            itm=order[indx];
            tem= alphaSort(a[itm], b[itm]); 
            indx+=1;        
        }
        return tem;
    });
    return this;
}

var arr= [[ "Nilesh","Karmshil"], ["Pranjal","Deka"], ["Susants","Ghosh"],
["Shiv","Shankar"], ["Javid","Ghosh"], ["Shaher","Banu"], ["Javid","Rashid"]];

arr.deepSortAlpha(1,0);

ขอทราบว่าคุณเก็บข้อมูลนี้มาจากไหน [["Nilesh", "Karmshil"], ["Pranjal", "Deka"], ["Susants", "Ghosh"], ["Shiv", "Shankar"] , ["Javid", "Ghosh"], ["Shaher", "Banu"], ["Javid", "Rashid"]];
defau1t

11

ฉันแนะนำให้ใช้ตัวเปรียบเทียบในตัวและเชื่อมโยงลำดับการจัดเรียงที่ต้องการด้วยตรรกะหรือ||.

function customSort(a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
}

ตัวอย่างการทำงาน:

var array = [
    [0, 'Aluminium', 0, 'Francis'],
    [1, 'Argon', 1, 'Ada'],
    [2, 'Brom', 2, 'John'],
    [3, 'Cadmium', 3, 'Marie'],
    [4, 'Fluor', 3, 'Marie'],
    [5, 'Gold', 1, 'Ada'],
    [6, 'Kupfer', 4, 'Ines'],
    [7, 'Krypton', 4, 'Joe'],
    [8, 'Sauerstoff', 3, 'Marie'],
    [9, 'Zink', 5, 'Max']
];

array.sort(function (a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
});

document.write('<pre>');
array.forEach(function (a) {
    document.write(JSON.stringify(a) + '<br>');
});


สิ่งนี้ได้ผลดีสำหรับฉัน! เข้าใจง่ายด้วย ขอบคุณ!
DanCue

นี่ไง!!! *****
Fredrik Johansson

8

คุณสามารถรวม 2 ตัวแปรเข้าด้วยกันเป็นคีย์การเรียงลำดับและใช้เพื่อเปรียบเทียบ

list.sort(function(a,b){
   var aCat = a.var1 + a.var2;
   var bCat = b.var1 + b.var2;
   return (aCat > bCat ? 1 : aCat < bCat ? -1 : 0);
});

@GustavoRodrigues อาจจะเพราะมันเปราะเกินไป มันจะล้มเหลวในการจัดเรียงตามแบบที่คาดไว้ในปุ่มป้อนข้อมูลบางปุ่มเนื่องจากมันจะรวมทั้งสองส่วนเข้าด้วยกันโดยไม่มีตัวคั่นหรือความแตกต่างอื่น ๆ พิจารณาว่า var1 และ var2 สำหรับรายการ X เป็น "foo" และ "baz" หรือไม่ในขณะที่ var1 สำหรับรายการ Y คือ "foobar" เมื่อเรียง X ควรมาก่อน แต่ในกรณีนี้จะเป็นอันดับสอง คำตอบนี้สามารถปรับปรุงได้ แต่ตามที่ระบุไว้มันไม่ปลอดภัย
Peter Hansen

4

ผมพบว่าmultisotr นี่เป็นไลบรารีที่เรียบง่ายมีประสิทธิภาพและมีขนาดเล็กสำหรับการจัดเรียงหลายรายการ ฉันจำเป็นต้องจัดเรียงอาร์เรย์ของวัตถุด้วยเกณฑ์การเรียงลำดับพลวัต:

const criteria = ['name', 'speciality']
const data = [
  { name: 'Mike', speciality: 'JS', age: 22 },
  { name: 'Tom', speciality: 'Java', age: 30 },
  { name: 'Mike', speciality: 'PHP', age: 40 },
  { name: 'Abby', speciality: 'Design', age: 20 },
]

const sorted = multisort(data, criteria)

console.log(sorted)
<script src="https://cdn.rawgit.com/peterkhayes/multisort/master/multisort.js"></script>

ห้องสมุดนี้มีพลังมากขึ้นนั่นคือกรณีของฉัน ลองมัน.


2

ฉันทำงานด้วยng-gridและจำเป็นต้องจัดเรียงคอลัมน์หลายคอลัมน์ในอาร์เรย์ของเร็กคอร์ดที่ส่งคืนจาก API ดังนั้นฉันจึงได้มาพร้อมกับฟังก์ชันการเรียงลำดับแบบไดนามิกที่ดีเยี่ยมนี้

ก่อนอื่นให้เริ่มng-gridการทำงาน "เหตุการณ์" สำหรับ "ngGridSorted" และส่งผ่านโครงสร้างนี้กลับโดยอธิบายการจัดเรียง:

sortData = {
    columns:    DOM Element,
    directions: [], //Array of string values desc or asc. Each index relating to the same index of fields
    fields:     [], //Array of string values
};

ดังนั้นฉันจึงสร้างฟังก์ชันที่จะสร้างฟังก์ชันการเรียงลำดับแบบไดนามิกตามที่sortDataแสดงไว้ด้านบน ( อย่ากลัวแถบเลื่อนมันยาวประมาณ 50 บรรทัดเท่านั้น! นอกจากนี้ฉันขอโทษด้วยเกี่ยวกับ slop ที่ป้องกันไม่ให้เกิดแนวนอน แถบเลื่อน! ):

function SortingFunction(sortData)
{
    this.sortData = sortData;

    this.sort = function(a, b)
    {
        var retval = 0;

        if(this.sortData.fields.length)
        {
            var i = 0;

            /*
                Determine if there is a column that both entities (a and b)
                have that are not exactly equal. The first one that we find
                will be the column we sort on. If a valid column is not
                located, then we will return 0 (equal).
            */
            while(  (   !a.hasOwnProperty(this.sortData.fields[i]) 
                    ||  !b.hasOwnProperty(this.sortData.fields[i]) 
                    ||  (a.hasOwnProperty(this.sortData.fields[i]) 
                        && b.hasOwnProperty(this.sortData.fields[i]) 
                        && a[this.sortData.fields[i]] === b[this.sortData.fields[i]])
                    ) && i < this.sortData.fields.length){
                i++;
            }

            if(i < this.sortData.fields.length)
            {
                /*
                    A valid column was located for both entities
                    in the SortData. Now perform the sort.
                */
                if(this.sortData.directions 
                && i < this.sortData.directions.length 
                && this.sortData.directions[i] === 'desc')
                {
                    if(a[this.sortData.fields[i]] > b[this.sortData.fields[i]])
                        retval = -1;
                    else if(a[this.sortData.fields[i]] < b[this.sortData.fields[i]])
                        retval = 1;
                }
                else
                {
                    if(a[this.sortData.fields[i]] < b[this.sortData.fields[i]])
                        retval = -1;
                    else if(a[this.sortData.fields[i]] > b[this.sortData.fields[i]])
                        retval = 1;
                }
            }
        }

        return retval;
    }.bind(this);
}

จากนั้นฉันเรียงลำดับผลลัพธ์ของ API ของฉัน ( results) ดังนี้:

results.sort(new SortingFunction(sortData).sort);

ฉันหวังว่าจะมีคนอื่นชอบวิธีนี้มากพอ ๆ กับที่ฉันทำ ขอบคุณ!


ตัวเลือกคอลัมน์บนข้อมูลการจัดเรียงใช้สำหรับอะไร
Alex Hope O'Connor

2

ลองสิ่งนี้:

t.sort( (a,b)=> a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]) );

ฉันถือว่าข้อมูลของคุณอยู่ในอาร์เรย์let t = [ [publicationID, publication_name, ownderID, owner_name ], ... ]โดยที่ index of owner_name = 3 และ publication_name = 1


2

วิธีการต่อท้ายสตริง

คุณสามารถจัดเรียงตามค่าต่างๆได้ง่ายๆเพียงต่อท้ายค่าลงในสตริงและเปรียบเทียบสตริง การเพิ่มอักขระคีย์แยกเพื่อป้องกันการไหลจากคีย์หนึ่งไปยังคีย์ถัดไปจะเป็นประโยชน์

ตัวอย่าง

const arr = [ 
    { a: 1, b: 'a', c: 3 },
    { a: 2, b: 'a', c: 5 },
    { a: 1, b: 'b', c: 4 },
    { a: 2, b: 'a', c: 4 }
]


function sortBy (arr, keys, splitKeyChar='~') {
    return arr.sort((i1,i2) => {
        const sortStr1 = keys.reduce((str, key) => str + splitKeyChar+i1[key], '')
        const sortStr2 = keys.reduce((str, key) => str + splitKeyChar+i2[key], '')
        return sortStr1.localeCompare(sortStr2)
    })
}

console.log(sortBy(arr, ['a', 'b', 'c']))


1
function multiSort() {

    var args =$.makeArray( arguments ),
        sortOrder=1, prop='', aa='',  b='';

    return function (a, b) {

       for (var i=0; i<args.length; i++){

         if(args[i][0]==='-'){
            prop=args[i].substr(1)
            sortOrder=-1
         }
         else{sortOrder=1; prop=args[i]}

         aa = a[prop].toLowerCase()
         bb = b[prop].toLowerCase()

         if (aa < bb) return -1 * sortOrder;
         if (aa > bb) return 1 * sortOrder;

       }

       return 0
    }

}
empArray.sort(multiSort( 'lastname','firstname')) Reverse with '-lastname'

1

ฉันมีปัญหาที่คล้ายกันในขณะที่แสดงบล็อกพูลหน่วยความจำจากผลลัพธ์ขององค์ประกอบฟังก์ชัน DOM เสมือนบางส่วนของ DOM โดยทั่วไปฉันประสบปัญหาเดียวกันกับการจัดเรียงข้อมูลหลายเกณฑ์เช่นการให้คะแนนจากผู้เล่นทั่วโลก

ฉันสังเกตเห็นว่าการเรียงลำดับหลายเกณฑ์คือ:

- sort by the first column
- if equal, sort by the second
- if equal, sort by the third
-  etc... nesting and nesting if-else

และถ้าคุณไม่สนใจคุณอาจล้มเหลวได้อย่างรวดเร็วในนรกที่กำลังรังอยู่ ... เหมือนนรกแห่งคำสัญญา ...

แล้วถ้าเราเขียนฟังก์ชัน "เพรดิเคต" เพื่อตัดสินใจว่าจะใช้ส่วนใดของทางเลือก? เพรดิเคตเป็นเพียง:

// useful for chaining test
const decide = (test, other) => test === 0 ? other : test

หลังจากเขียนการทดสอบการจำแนกประเภทของคุณแล้ว (byCountrySize, byAge, byGameType, byScore, byLevel ... ) สิ่งที่ต้องการคุณสามารถถ่วงน้ำหนักการทดสอบของคุณ (1 = asc, -1 = desc, 0 = ปิดการใช้งาน) ใส่ไว้ในอาร์เรย์ และใช้ฟังก์ชันลด 'ตัดสินใจ' ดังนี้:

const multisort = (s1, s2) => {
  const bcs = -1 * byCountrySize(s1, s2) // -1 = desc 
  const ba =  1 *byAge(s1, s2)
  const bgt = 0 * byGameType(s1, s2) // 0 = doesn't matter
  const bs = 1 * byScore(s1, s2)
  const bl = -1 * byLevel(s1, s2) // -1 = desc

  // ... other weights and criterias

  // array order matters !
  return [bcs, ba, bgt, bs, bl].reduce((acc, val) => decide(val, acc), 0)
}

// invoke [].sort with custom sort...
scores.sort(multisort)

และ voila! ขึ้นอยู่กับคุณที่จะกำหนดเกณฑ์ / น้ำหนัก / คำสั่งซื้อของคุณเอง ... แต่คุณได้รับแนวคิด หวังว่านี่จะช่วยได้!

แก้ไข: * ตรวจสอบให้แน่ใจว่ามีลำดับการจัดเรียงทั้งหมดในแต่ละคอลัมน์ * ระวังว่าไม่มีการอ้างอิงระหว่างคำสั่งคอลัมน์และไม่มีการอ้างอิงแบบวงกลม

ถ้าไม่การเรียงลำดับอาจไม่เสถียร!


1

ไลบรารีของฉันเองสำหรับการทำงานกับ ES6 iterables (blinq)ช่วยให้ (เหนือสิ่งอื่นใด) การเรียงลำดับหลายระดับที่ง่ายดาย

const blinq = window.blinq.blinq
// or import { blinq } from 'blinq'
// or const { blinq } = require('blinq')
const dates = [{
    day: 1, month: 10, year: 2000
  },
  {
    day: 1, month: 1, year: 2000
  },
  {
    day: 2, month: 1, year: 2000
  },
  {
    day: 1, month: 1, year: 1999
  },
  {
    day: 1, month: 1, year: 2000
  }
]
const sortedDates = blinq(dates)
  .orderBy(x => x.year)
  .thenBy(x => x.month)
  .thenBy(x => x.day);

console.log(sortedDates.toArray())
// or console.log([...sortedDates])
<script src="https://cdn.jsdelivr.net/npm/blinq@2.0.2"></script>


0

มาจากGitHub

function sortMethodAsc(a, b) {
    return a == b ? 0 : a > b ? 1 : -1;
}

function sortMethodWithDirection(direction) { 
    if (direction === undefined || direction == "asc") {
        return sortMethodAsc;
    } else {
        return function(a, b) {
            return -sortMethodAsc(a, b);
        } 
    }
}

function sortMethodWithDirectionByColumn(columnName, direction){   
    const sortMethod = sortMethodWithDirection(direction)
    return function(a, b){
        return sortMethod(a[columnName], b[columnName]);
    } 
}

function sortMethodWithDirectionMultiColumn(sortArray) {
    //sample of sortArray
    // sortArray = [
    //     { column: "column5", direction: "asc" },
    //     { column: "column3", direction: "desc" }
    // ]
    const sortMethodsForColumn = (sortArray || []).map( item => sortMethodWithDirectionByColumn(item.column, item.direction) );
    return function(a,b) {
        let sorted = 0;
        let index = 0;
        while (sorted === 0 && index < sortMethodsForColumn.length) {
            sorted = sortMethodsForColumn[index++](a,b);
        }
        return sorted;
    }
} 

//=============================================
//=============================================
//=============================================
//test

var data = [
    {"CountryName":"Aruba","CountryCode":"ABW","GNI":280},{
        "CountryName":"Afghanistan","CountryCode":"ABW","GNI":280},{"CountryName":"Angola","CountryCode":"AGO","GNI":280},{"CountryName":"Albania","CountryCode":"ALB","GNI":4320},
        {"CountryName":"Arab World","CountryCode":"ARB","GNI":280},{"CountryName":"United Arab Emirates","CountryCode":"ARE","GNI":39130},
        {"CountryName":"Argentina","CountryCode":"ARG","GNI":13030},{"CountryName":"Armenia","CountryCode":"ARM","GNI":3990},{"CountryName":"American Samoa","CountryCode":"ASM","GNI":280},
        {"CountryName":"Antigua and Barbuda","CountryCode":"ATG","GNI":13810},{"CountryName":"Australia","CountryCode":"AUS","GNI":51360},
        {"CountryName":"Austria","CountryCode":"AUT","GNI":45440},{"CountryName":"Azerbaijan","CountryCode":"AZE","GNI":4080},{"CountryName":"Burundi","CountryCode":"BDI","GNI":280},
        {"CountryName":"Belgium","CountryCode":"BEL","GNI":41790},{"CountryName":"Benin","CountryCode":"BEN","GNI":800},{"CountryName":"Burkina Faso","CountryCode":"BFA","GNI":590},
        {"CountryName":"Bangladesh","CountryCode":"BGD","GNI":1470},{"CountryName":"Bulgaria","CountryCode":"BGR","GNI":7860},{"CountryName":"Bahrain","CountryCode":"BHR","GNI":21150},
        {"CountryName":"Bosnia and Herzegovina","CountryCode":"BIH","GNI":4910},{"CountryName":"Belarus","CountryCode":"BLR","GNI":5280},
        {"CountryName":"Belize","CountryCode":"BLZ","GNI":4390},{"CountryName":"Bolivia","CountryCode":"BOL","GNI":3130},{"CountryName":"Brazil","CountryCode":"BRA","GNI":8600},
        {"CountryName":"Barbados","CountryCode":"BRB","GNI":15270},{"CountryName":"Brunei Darussalam","CountryCode":"BRN","GNI":29600},
        {"CountryName":"Bhutan","CountryCode":"BTN","GNI":2660},{"CountryName":"Botswana","CountryCode":"BWA","GNI":6730},
        {"CountryName":"Central African Republic","CountryCode":"CAF","GNI":390},{"CountryName":"Canada","CountryCode":"CAN","GNI":42870},
        {"CountryName":"Central Europe and the Baltics","CountryCode":"CEB","GNI":13009},{"CountryName":"Switzerland","CountryCode":"CHE","GNI":80560},
        {"CountryName":"Chile","CountryCode":"CHL","GNI":13610},{"CountryName":"China","CountryCode":"CHN","GNI":8690},{"CountryName":"Cote d'Ivoire","CountryCode":"CIV","GNI":1580},
        {"CountryName":"Cameroon","CountryCode":"CMR","GNI":1370},{"CountryName":"Colombia","CountryCode":"COL","GNI":5890},{"CountryName":"Comoros","CountryCode":"COM","GNI":1280},
        {"CountryName":"Cabo Verde","CountryCode":"CPV","GNI":3030},{"CountryName":"Costa Rica","CountryCode":"CRI","GNI":11120},
        {"CountryName":"Caribbean small states","CountryCode":"CSS","GNI":8909},{"CountryName":"Cyprus","CountryCode":"CYP","GNI":23720},
        {"CountryName":"Czech Republic","CountryCode":"CZE","GNI":18160},{"CountryName":"Germany","CountryCode":"DEU","GNI":43490},
        {"CountryName":"Djibouti","CountryCode":"DJI","GNI":1880},{"CountryName":"Dominica","CountryCode":"DMA","GNI":6590},{"CountryName":"Denmark","CountryCode":"DNK","GNI":55220},
        {"CountryName":"Dominican Republic","CountryCode":"DOM","GNI":6630},{"CountryName":"Algeria","CountryCode":"DZA","GNI":3940},
        {"CountryName":"East Asia & Pacific (excluding high income)","CountryCode":"EAP","GNI":6987},{"CountryName":"Early-demographic dividend","CountryCode":"EAR","GNI":3352},
        {"CountryName":"East Asia & Pacific","CountryCode":"EAS","GNI":10171},{"CountryName":"Europe & Central Asia (excluding high income)","CountryCode":"ECA","GNI":7375},
        {"CountryName":"Europe & Central Asia","CountryCode":"ECS","GNI":22656},{"CountryName":"Ecuador","CountryCode":"ECU","GNI":5920},
        {"CountryName":"Euro area","CountryCode":"EMU","GNI":35645},{"CountryName":"Spain","CountryCode":"ESP","GNI":27180},{"CountryName":"Estonia","CountryCode":"EST","GNI":18190},
        {"CountryName":"Ethiopia","CountryCode":"ETH","GNI":740},{"CountryName":"European Union","CountryCode":"EUU","GNI":32784},
        {"CountryName":"Fragile and conflict affected situations","CountryCode":"FCS","GNI":1510},{"CountryName":"Finland","CountryCode":"FIN","GNI":44580},
        {"CountryName":"Fiji","CountryCode":"FJI","GNI":4970},{"CountryName":"France","CountryCode":"FRA","GNI":37970},{"CountryName":"Gabon","CountryCode":"GAB","GNI":6650},
        {"CountryName":"United Kingdom","CountryCode":"GBR","GNI":40530},{"CountryName":"Georgia","CountryCode":"GEO","GNI":3780},{"CountryName":"Ghana","CountryCode":"GHA","GNI":1880},
        {"CountryName":"Guinea","CountryCode":"GIN","GNI":790},{"CountryName":"Guinea-Bissau","CountryCode":"GNB","GNI":660},
        {"CountryName":"Equatorial Guinea","CountryCode":"GNQ","GNI":7050},{"CountryName":"Greece","CountryCode":"GRC","GNI":18090},
        {"CountryName":"Grenada","CountryCode":"GRD","GNI":9180},{"CountryName":"Guatemala","CountryCode":"GTM","GNI":4060},{"CountryName":"Guyana","CountryCode":"GUY","GNI":4500},
        {"CountryName":"High income","CountryCode":"HIC","GNI":40142},{"CountryName":"Honduras","CountryCode":"HND","GNI":2250},{"CountryName":"Heavily indebted poor countries (HIPC)","CountryCode":"HPC","GNI":904},{"CountryName":"Croatia","CountryCode":"HRV","GNI":12570},{"CountryName":"Haiti","CountryCode":"HTI","GNI":760},{"CountryName":"Hungary","CountryCode":"HUN","GNI":12870},{"CountryName":"IBRD only","CountryCode":"IBD","GNI":5745},{"CountryName":"IDA & IBRD total","CountryCode":"IBT","GNI":4620},{"CountryName":"IDA total","CountryCode":"IDA","GNI":1313},{"CountryName":"IDA blend","CountryCode":"IDB","GNI":1791},
        {"CountryName":"Indonesia","CountryCode":"IDN","GNI":3540},{"CountryName":"IDA only","CountryCode":"IDX","GNI":1074},{"CountryName":"India","CountryCode":"IND","GNI":1800},{"CountryName":"Ireland","CountryCode":"IRL","GNI":55290},{"CountryName":"Iraq","CountryCode":"IRQ","GNI":4630},{"CountryName":"Iceland","CountryCode":"ISL","GNI":60830},{"CountryName":"Israel","CountryCode":"ISR","GNI":37270},{"CountryName":"Italy","CountryCode":"ITA","GNI":31020},{"CountryName":"Jamaica","CountryCode":"JAM","GNI":4760},{"CountryName":"Jordan","CountryCode":"JOR","GNI":3980},{"CountryName":"Japan","CountryCode":"JPN","GNI":38550},{"CountryName":"Kazakhstan","CountryCode":"KAZ","GNI":7970},{"CountryName":"Kenya","CountryCode":"KEN","GNI":1460},{"CountryName":"Kyrgyz Republic","CountryCode":"KGZ","GNI":1130},
        {"CountryName":"Cambodia","CountryCode":"KHM","GNI":1230},{"CountryName":"Kiribati","CountryCode":"KIR","GNI":3010},{"CountryName":"St. Kitts and Nevis","CountryCode":"KNA","GNI":16240},{"CountryName":"Kuwait","CountryCode":"KWT","GNI":31430},{"CountryName":"Latin America & Caribbean (excluding high income)","CountryCode":"LAC","GNI":7470},{"CountryName":"Lao PDR","CountryCode":"LAO","GNI":2270},{"CountryName":"Lebanon","CountryCode":"LBN","GNI":8400},{"CountryName":"Liberia","CountryCode":"LBR","GNI":620},{"CountryName":"Libya","CountryCode":"LBY","GNI":5500},{"CountryName":"St. Lucia","CountryCode":"LCA","GNI":8830},{"CountryName":"Latin America & Caribbean","CountryCode":"LCN","GNI":8251},{"CountryName":"Least developed countries: UN classification","CountryCode":"LDC","GNI":1011},{"CountryName":"Low income","CountryCode":"LIC","GNI":774},{"CountryName":"Sri Lanka","CountryCode":"LKA","GNI":3850},{"CountryName":"Lower middle income","CountryCode":"LMC","GNI":2118},{"CountryName":"Low & middle income","CountryCode":"LMY","GNI":4455},{"CountryName":"Lesotho","CountryCode":"LSO","GNI":1210},{"CountryName":"Late-demographic dividend","CountryCode":"LTE","GNI":8518},{"CountryName":"Lithuania","CountryCode":"LTU","GNI":15200},{"CountryName":"Luxembourg","CountryCode":"LUX","GNI":70260},{"CountryName":"Latvia","CountryCode":"LVA","GNI":14740},{"CountryName":"Morocco","CountryCode":"MAR","GNI":2860},{"CountryName":"Moldova","CountryCode":"MDA","GNI":2200},{"CountryName":"Madagascar","CountryCode":"MDG","GNI":400},{"CountryName":"Maldives","CountryCode":"MDV","GNI":9760},
        {"CountryName":"Middle East & North Africa","CountryCode":"MEA","GNI":7236},{"CountryName":"Mexico","CountryCode":"MEX","GNI":8610},{"CountryName":"Marshall Islands","CountryCode":"MHL","GNI":4840},{"CountryName":"Middle income","CountryCode":"MIC","GNI":4942},{"CountryName":"Mali","CountryCode":"MLI","GNI":770},
        {"CountryName":"Malta","CountryCode":"MLT","GNI":24080},{"CountryName":"Myanmar","CountryCode":"MMR","GNI":1210},{"CountryName":"Middle East & North Africa (excluding high income)","CountryCode":"MNA","GNI":3832},{"CountryName":"Montenegro","CountryCode":"MNE","GNI":7400},{"CountryName":"Mongolia","CountryCode":"MNG","GNI":3270},{"CountryName":"Mozambique","CountryCode":"MOZ","GNI":420},{"CountryName":"Mauritania","CountryCode":"MRT","GNI":1100},{"CountryName":"Mauritius","CountryCode":"MUS","GNI":10130},{"CountryName":"Malawi","CountryCode":"MWI","GNI":320},{"CountryName":"Malaysia","CountryCode":"MYS","GNI":9650},{"CountryName":"North America","CountryCode":"NAC","GNI":56721},{"CountryName":"Namibia","CountryCode":"NAM","GNI":4570},{"CountryName":"Niger","CountryCode":"NER","GNI":360},{"CountryName":"Nigeria","CountryCode":"NGA","GNI":2100},
        {"CountryName":"Nicaragua","CountryCode":"NIC","GNI":2130},{"CountryName":"Netherlands","CountryCode":"NLD","GNI":46180},{"CountryName":"Norway","CountryCode":"NOR","GNI":75990},{"CountryName":"Nepal","CountryCode":"NPL","GNI":800},{"CountryName":"Nauru","CountryCode":"NRU","GNI":10220},{"CountryName":"New Zealand","CountryCode":"NZL","GNI":38970},{"CountryName":"OECD members","CountryCode":"OED","GNI":37273},{"CountryName":"Oman","CountryCode":"OMN","GNI":14440},{"CountryName":"Other small states","CountryCode":"OSS","GNI":12199},{"CountryName":"Pakistan","CountryCode":"PAK","GNI":1580},{"CountryName":"Panama","CountryCode":"PAN","GNI":13280},{"CountryName":"Peru","CountryCode":"PER","GNI":5960},{"CountryName":"Philippines","CountryCode":"PHL","GNI":3660},{"CountryName":"Palau","CountryCode":"PLW","GNI":12700},{"CountryName":"Papua New Guinea","CountryCode":"PNG","GNI":2340},{"CountryName":"Poland","CountryCode":"POL","GNI":12730},{"CountryName":"Pre-demographic dividend","CountryCode":"PRE","GNI":1379},{"CountryName":"Portugal","CountryCode":"PRT","GNI":19820},{"CountryName":"Paraguay","CountryCode":"PRY","GNI":5470},{"CountryName":"West Bank and Gaza","CountryCode":"PSE","GNI":3180},{"CountryName":"Pacific island small states","CountryCode":"PSS","GNI":3793},{"CountryName":"Post-demographic dividend","CountryCode":"PST","GNI":41609},{"CountryName":"Qatar","CountryCode":"QAT","GNI":60510},{"CountryName":"Romania","CountryCode":"ROU","GNI":10000},{"CountryName":"Russian Federation","CountryCode":"RUS","GNI":9230},{"CountryName":"Rwanda","CountryCode":"RWA","GNI":720},{"CountryName":"South Asia","CountryCode":"SAS","GNI":1729},{"CountryName":"Saudi Arabia","CountryCode":"SAU","GNI":20090},{"CountryName":"Sudan","CountryCode":"SDN","GNI":2380},{"CountryName":"Senegal","CountryCode":"SEN","GNI":1240},{"CountryName":"Singapore","CountryCode":"SGP","GNI":54530},{"CountryName":"Solomon Islands","CountryCode":"SLB","GNI":1920},{"CountryName":"Sierra Leone","CountryCode":"SLE","GNI":510},{"CountryName":"El Salvador","CountryCode":"SLV","GNI":3560},{"CountryName":"Serbia","CountryCode":"SRB","GNI":5180},{"CountryName":"Sub-Saharan Africa (excluding high income)","CountryCode":"SSA","GNI":1485},{"CountryName":"Sub-Saharan Africa","CountryCode":"SSF","GNI":1486},{"CountryName":"Small states","CountryCode":"SST","GNI":11099},{"CountryName":"Sao Tome and Principe","CountryCode":"STP","GNI":1770},{"CountryName":"Suriname","CountryCode":"SUR","GNI":5150},{"CountryName":"Slovak Republic","CountryCode":"SVK","GNI":16610},{"CountryName":"Slovenia","CountryCode":"SVN","GNI":22000},{"CountryName":"Sweden","CountryCode":"SWE","GNI":52590},{"CountryName":"Eswatini","CountryCode":"SWZ","GNI":2950},{"CountryName":"Seychelles","CountryCode":"SYC","GNI":14170},{"CountryName":"Chad","CountryCode":"TCD","GNI":640},{"CountryName":"East Asia & Pacific (IDA & IBRD countries)","CountryCode":"TEA","GNI":7061},
        {"CountryName":"Europe & Central Asia (IDA & IBRD countries)","CountryCode":"TEC","GNI":7866},{"CountryName":"Togo","CountryCode":"TGO","GNI":610},{"CountryName":"Thailand","CountryCode":"THA","GNI":5950},{"CountryName":"Tajikistan","CountryCode":"TJK","GNI":990},{"CountryName":"Turkmenistan","CountryCode":"TKM","GNI":6380},{"CountryName":"Latin America & the Caribbean (IDA & IBRD countries)","CountryCode":"TLA","GNI":8179},{"CountryName":"Timor-Leste","CountryCode":"TLS","GNI":1790},{"CountryName":"Middle East & North Africa (IDA & IBRD countries)","CountryCode":"TMN","GNI":3839},{"CountryName":"Tonga","CountryCode":"TON","GNI":4010},{"CountryName":"South Asia (IDA & IBRD)","CountryCode":"TSA","GNI":1729},
        {"CountryName":"Sub-Saharan Africa (IDA & IBRD countries)","CountryCode":"TSS","GNI":1486},{"CountryName":"Trinidad and Tobago","CountryCode":"TTO","GNI":15340},{"CountryName":"Tunisia","CountryCode":"TUN","GNI":3490},{"CountryName":"Turkey","CountryCode":"TUR","GNI":10940},{"CountryName":"Tuvalu","CountryCode":"TUV","GNI":4970},{"CountryName":"Tanzania","CountryCode":"TZA","GNI":910},{"CountryName":"Uganda","CountryCode":"UGA","GNI":600},{"CountryName":"Ukraine","CountryCode":"UKR","GNI":2390},{"CountryName":"Upper middle income","CountryCode":"UMC","GNI":8197},{"CountryName":"Uruguay","CountryCode":"URY","GNI":15250},{"CountryName":"United States","CountryCode":"USA","GNI":58270},{"CountryName":"Uzbekistan","CountryCode":"UZB","GNI":2000},{"CountryName":"St. Vincent and the Grenadines","CountryCode":"VCT","GNI":7390},{"CountryName":"Vietnam","CountryCode":"VNM","GNI":2160},{"CountryName":"Vanuatu","CountryCode":"VUT","GNI":2920},{"CountryName":"World","CountryCode":"WLD","GNI":10371},{"CountryName":"Samoa","CountryCode":"WSM","GNI":4090},{"CountryName":"Kosovo","CountryCode":"XKX","GNI":3900},
        {"CountryName":"South Africa","CountryCode":"ZAF","GNI":5430},{"CountryName":"Zambia","CountryCode":"ZMB","GNI":1290},{"CountryName":"Zimbabwe","CountryCode":"ZWE","GNI":1170},
        {"CountryName":"Zimbabwe","CountryCode":"ZWE","GNI":1171}];

    const sortMethod = sortMethodWithDirectionMultiColumn(
        [
            { column: "GNI", direction: "asc" },
            { column: "CountryCode", direction: "desc" }
        ]
    );
    let sortedData = data.sort(sortMethod);  
    
    
    console.log("sorted by: 1)column:GNI-asc, 2)column:CountryCode-desc") 
    console.table(sortedData);
    console.log(sortedData);
    


ยินดีต้อนรับสู่ stackoverflow นอกเหนือจากคำตอบที่คุณให้ไว้โปรดพิจารณาให้คำอธิบายสั้น ๆ ว่าเหตุใดจึงแก้ไขปัญหานี้ได้อย่างไร
jtate

0

ฉันได้รับการตีพิมพ์เพียงเพื่อ NPM ไมโครห้องสมุดเรียกว่าเรียงลำดับผู้ช่วย ( แหล่งที่มาบน GitHub ) แนวคิดคือการนำเข้าตัวช่วยbyเพื่อสร้างฟังก์ชันเปรียบเทียบสำหรับsortวิธีอาร์เรย์ผ่านทางไวยากรณ์items.sort(by(column, ...otherColumns))โดยมีหลายวิธีในการแสดงคอลัมน์เพื่อจัดเรียงตาม:

  • ตามคีย์ : persons.sort(by('lastName', 'firstName')),
  • ตามตัวเลือก : dates.sort(by(x => x.toISOString())),
  • ในลำดับถัดลงมา : [3, 2, 4, 1].sort(by(desc(n => n)))[3, 2, 1, 0],
  • ไม่สนใจกรณี : ['B', 'D', 'c', 'a'].sort(by(ignoreCase(x => x))).join('')'aBcD'.

คล้ายกับสิ่งที่ดีตามที่กล่าวไว้ในคำตอบนี้แต่ด้วยความแตกต่างต่อไปนี้ที่อาจมากกว่าสำหรับรสนิยมของบางคน:

  • วิธีการทำงานมากกว่าเชิงวัตถุ(ดูthenByAPI อย่างคล่องแคล่ว) ,
  • ไวยากรณ์ค่อนข้างสั้นและยังคงอ่านได้เป็นธรรมชาติเกือบจะเหมือนกับ SQL
  • ใช้งานได้อย่างสมบูรณ์ใน TypeScript เพื่อรับประโยชน์จากความปลอดภัยของประเภทและการแสดงออกของประเภท
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.