การเรียงลำดับวัตถุตามค่าคุณสมบัติ


89

วิธีใช้สถานการณ์ต่อไปนี้โดยใช้ Javascript เท่านั้น:

  • สร้างวัตถุรถยนต์ที่มีคุณสมบัติ (ความเร็วสูงสุดยี่ห้อ ฯลฯ )
  • จัดเรียงรายการรถที่เรียงตามคุณสมบัติเหล่านั้น

3
@durilai: JavaScript เป็นแบบเชิงวัตถุรูปแบบ OO ของ JavaScript นั้นขึ้นอยู่กับPrototypingและมีความหลากหลายจริงๆ ... th.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó

ฉันแนะนำให้ใช้ lodash.js: lodash.com/docs#sortBy
Chemical Programmer

คำตอบ:


163

javascript มีฟังก์ชันsortซึ่งสามารถใช้ฟังก์ชันอื่นเป็นพารามิเตอร์ - ฟังก์ชันที่สองนั้นใช้เพื่อเปรียบเทียบสององค์ประกอบ

ตัวอย่าง:

cars = [

    {
        name: "Honda",
        speed: 80
    },

    {
        name: "BMW",
        speed: 180
    },

    {
        name: "Trabi",
        speed: 40
    },

    {
        name: "Ferrari",
        speed: 200
    }
]


cars.sort(function(a, b) { 
    return a.speed - b.speed;
})

for(var i in cars)
    document.writeln(cars[i].name) // Trabi Honda BMW Ferrari 

โอเคจากความคิดเห็นของคุณฉันเห็นว่าคุณใช้คำว่า 'เรียงลำดับ' ในความหมายที่ไม่ถูกต้อง ในการเขียนโปรแกรม "sort" หมายถึง "จัดเรียงสิ่งต่างๆตามลำดับ" ไม่ใช่ "จัดเรียงสิ่งต่างๆเป็นกลุ่ม" อย่างหลังง่ายกว่ามากนี่คือวิธีที่คุณ "จัดเรียง" สิ่งต่างๆในโลกแห่งความเป็นจริง

  • สร้างอาร์เรย์ว่างสองอาร์เรย์ ("กล่อง")
  • สำหรับแต่ละออบเจ็กต์ในรายการของคุณตรวจสอบว่าตรงกับเกณฑ์หรือไม่
  • ถ้าใช่ใส่ไว้ใน "ช่อง" แรก
  • ถ้าไม่มีให้ใส่ลงใน "กล่อง" ที่สอง

11
หมายเหตุง่ายๆเพื่อความสะดวก: ( a.someProp - b.someProp) เรียงลำดับจากต่ำสุดไปสูงสุดและย้อนกลับ ( b.someProp - a.someProp) เรียงลำดับจากสูงสุดไปต่ำสุด โดยทั่วไปถ้าฟังก์ชันคืนค่าน้อยกว่า 0 a มาก่อน b
user56reinstatemonica8

โปรดทราบว่าโซลูชันนี้ใช้ได้เฉพาะเมื่อคุณสมบัติที่คุณจัดเรียงเป็นตัวเลขเท่านั้น วิธีนี้ใช้ได้ในตัวอย่างสำหรับการจัดเรียงตามความเร็วสูงสุด แต่ถ้าคุณต้องการจัดเรียงตามยี่ห้อรถยนต์โซลูชันนี้จะไม่จัดเรียงสตริงตามตัวอักษร Cheeso ให้คำตอบสำหรับการเรียงลำดับตามทั้งตัวเลขและสตริง
Cole Marshall

23

ตัวอย่าง.

สิ่งนี้ทำงานบน cscript.exe บน windows

// define the Car class
(function() {
    // makeClass - By John Resig (MIT Licensed)
    // Allows either new User() or User() to be employed for construction.
    function makeClass(){
        return function(args){
            if ( this instanceof arguments.callee ) {
                if ( typeof this.init == "function" )
                    this.init.apply( this, (args && args.callee) ? args : arguments );
            } else
                return new arguments.callee( arguments );
        };
    }

    Car = makeClass();

    Car.prototype.init = function(make, model, price, topSpeed, weight) {
        this.make = make;
        this.model = model;
        this.price = price;
        this.weight = weight;
        this.topSpeed = topSpeed;
    };
})();


// create a list of cars
var autos = [
    new Car("Chevy", "Corvair", 1800, 88, 2900),
    new Car("Buick", "LeSabre", 31000, 138, 3700),
    new Car("Toyota", "Prius", 24000, 103, 3200),
    new Car("Porsche", "911", 92000, 155, 3100),
    new Car("Mercedes", "E500", 67000, 145, 3800),
    new Car("VW", "Passat", 31000, 135, 3700)
];

// a list of sorting functions
var sorters = {
    byWeight : function(a,b) {
        return (a.weight - b.weight);
    },
    bySpeed : function(a,b) {
        return (a.topSpeed - b.topSpeed);
    },
    byPrice : function(a,b) {
        return (a.price - b.price);
    },
    byModelName : function(a,b) {
        return ((a.model < b.model) ? -1 : ((a.model > b.model) ? 1 : 0));
    },
    byMake : function(a,b) {
        return ((a.make < b.make) ? -1 : ((a.make > b.make) ? 1 : 0));
    }
};

function say(s) {WScript.Echo(s);}

function show(title)
{
    say ("sorted by: "+title);
    for (var i=0; i < autos.length; i++) {
        say("  " + autos[i].model);
    }
    say(" ");
}

autos.sort(sorters.byWeight);
show("Weight");

autos.sort(sorters.byModelName);
show("Name");

autos.sort(sorters.byPrice);
show("Price");

คุณยังสามารถสร้างเครื่องเรียงลำดับทั่วไป

var byProperty = function(prop) {
    return function(a,b) {
        if (typeof a[prop] == "number") {
            return (a[prop] - b[prop]);
        } else {
            return ((a[prop] < b[prop]) ? -1 : ((a[prop] > b[prop]) ? 1 : 0));
        }
    };
};

autos.sort(byProperty("topSpeed"));
show("Top Speed");

13

ฉันได้เขียนฟังก์ชันง่ายๆสำหรับตัวฉันเอง:

function sortObj(list, key) {
    function compare(a, b) {
        a = a[key];
        b = b[key];
        var type = (typeof(a) === 'string' ||
                    typeof(b) === 'string') ? 'string' : 'number';
        var result;
        if (type === 'string') result = a.localeCompare(b);
        else result = a - b;
        return result;
    }
    return list.sort(compare);
}

ตัวอย่างเช่นคุณมีรายชื่อรถยนต์:

var cars= [{brand: 'audi', speed: 240}, {brand: 'fiat', speed: 190}];
var carsSortedByBrand = sortObj(cars, 'brand');
var carsSortedBySpeed = sortObj(cars, 'speed');

6

สมมติว่าเราต้องเรียงลำดับรายการของวัตถุจากน้อยไปหามากตามคุณสมบัติเฉพาะในตัวอย่างนี้สมมติว่าเราต้องเรียงลำดับตามคุณสมบัติ "name" จากนั้นรหัสที่ต้องการด้านล่าง:

var list_Objects = [{"name"="Bob"},{"name"="Jay"},{"name"="Abhi"}];
Console.log(list_Objects);   //[{"name"="Bob"},{"name"="Jay"},{"name"="Abhi"}]
    list_Objects.sort(function(a,b){
        return a["name"].localeCompare(b["name"]); 
    });
Console.log(list_Objects);  //[{"name"="Abhi"},{"name"="Bob"},{"name"="Jay"}]

1
ฉันคิดว่าคุณพิมพ์ผิด? ส่งคืน ["name"]. localeCompare (b. ["name"]); ควรจะส่งคืน ["name"] localeCompare (b ["name"]); (ลบ. หลัง b)
Little Brain

3

ด้วยฟังก์ชั่นลูกศร ES6จะเป็นดังนี้:

//Let's say we have these cars
let cars = [ { brand: 'Porsche', top_speed: 260 },
  { brand: 'Benz', top_speed: 110 },
  { brand: 'Fiat', top_speed: 90 },
  { brand: 'Aston Martin', top_speed: 70 } ]

Array.prototype.sort() สามารถรับฟังก์ชั่นเปรียบเทียบได้ (ที่นี่ฉันใช้สัญกรณ์ลูกศร แต่ฟังก์ชั่นทั่วไปทำงานเหมือนกัน):

let sortedByBrand = [...cars].sort((first, second) => first.brand > second.brand)

// [ { brand: 'Aston Martin', top_speed: 70 },
//   { brand: 'Benz', top_speed: 110 },
//   { brand: 'Fiat', top_speed: 90 },
//   { brand: 'Porsche', top_speed: 260 } ]

วิธีการข้างต้นจะคัดลอกเนื้อหาของอาร์เรย์รถยนต์ไปเป็นแบบใหม่และจัดเรียงตามตัวอักษรตามชื่อแบรนด์ ในทำนองเดียวกันคุณสามารถส่งผ่านฟังก์ชันต่างๆ:

let sortedBySpeed =[...cars].sort((first, second) => first.top_speed > second.top_speed)

//[ { brand: 'Aston Martin', top_speed: 70 },
//  { brand: 'Fiat', top_speed: 90 },
//  { brand: 'Benz', top_speed: 110 },
//  { brand: 'Porsche', top_speed: 260 } ]

หากคุณไม่รังเกียจที่cars.sort(comparatorFunction)จะเปลี่ยนอาร์เรย์เดิมจะเป็นการหลอกลวง


3

นี่คือตัวอย่างสั้น ๆ ที่สร้างและจัดเรียงวัตถุและเรียงลำดับตามตัวเลขหรือตามตัวอักษร:

// Create Objects Array

var arrayCarObjects = [
{brand: "Honda",        topSpeed: 45},
{brand: "Ford",         topSpeed: 6},
{brand: "Toyota",       topSpeed: 240},
{brand: "Chevrolet",    topSpeed: 120},
{brand: "Ferrari",      topSpeed: 1000}
];

// Sort Objects Numerically

arrayCarObjects.sort((a, b) => (a.topSpeed - b.topSpeed));

// Sort Objects Alphabetically

arrayCarObjects.sort((a, b) => (a.brand > b.brand) ? 1 : -1);

2

โซลูชัน Cheeso เวอร์ชันที่มีการเรียงลำดับแบบย้อนกลับฉันยังลบนิพจน์ที่เกี่ยวข้องเนื่องจากขาดความชัดเจน (แต่นี่เป็นรสนิยมส่วนตัว)

function(prop, reverse) {
  return function(a, b) {
    if (typeof a[prop] === 'number') {
      return (a[prop] - b[prop]);
    }

    if (a[prop] < b[prop]) {
      return reverse ? 1 : -1;
    }

    if (a[prop] > b[prop]) {
      return reverse ? -1 : 1;
    }

    return 0;
  };
};

1
หากต้องการย้อนกลับอย่างสมบูรณ์ตัวเลขต้องreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Mark Schultheiss

ใช่เนื่องจากตอนนี้ไม่มีการตรวจสอบตัวเลขแบบย้อนกลับขอบคุณฉันควรแก้ไข แต่ทำไมสองเท่า!นี้ก็ใช้ได้เช่นกัน:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Marcs

1
!!ประเภทกองกำลังบังคับให้เป็นค่าประเภทพื้นเมืองบูลเมื่อเทียบกับธรรมชาติ "falsy" ของมูลค่า JavaScript, ไม่จำเป็นต้องใช้อย่างเคร่งครัด แต่วัตถุประสงค์ชี้แจงอย่างน้อยให้ฉัน โปรดทราบว่าเมื่อคุณส่งคืนค่าโดย!!เป็นประเภทบูลีนเนทีฟซึ่งตรงข้ามกับประเภทเนทีฟที่มีค่า "เท็จ" ซึ่งเป็นการบอกว่าtypeof !!undefinedหรือtypeof !!nullอื่น ๆ ส่งคืน "บูลีน" หมายเหตุที่!!" "เป็นtrueแต่!!""เป็นfalse(ช่องว่างไม่มีช่องว่างใน สตริง) แต่คุณคงรู้แล้ว
Mark Schultheiss
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.