2015-08-13 30 views
5

Tôi đang cố gắng sắp xếp một mảng các đối tượng, trong ngữ cảnh này, và tôi đang cố gắng viết một hàm nơi người dùng có thể sắp xếp dãy nhà khoảng cách của một mốc. Nói rằng tôi đã dữ liệu sau trở về từ một API mà tôi đang kêu gọi thông qua AJAX:Cách sắp xếp một mảng theo giá trị của một đối tượng trong một mảng lồng nhau

"data" : [ 
    { 
     'id' : 123, 
     'address' : '12 street name', 
     'city' : 'City Name', 
     'landmarks' : [ 
      { 
       'name' : 'landmark one', 
       'distanceInMiles' : 0.6 
      }, 
      { 
       'name' : 'landmark two', 
       'distanceInMiles' : 0.4 
      } 
     ] 
    }, 
    { 
     'id' : 345, 
     'address' : '22 street name', 
     'city' : 'City Name', 
     'landmarks' : [ 
      { 
       'name' : 'landmark one', 
       'distanceInMiles' : 0.2 
      }, 
      { 
       'name' : 'landmark three', 
       'distanceInMiles' : 0.1 
      } 
     ] 
    }, 
    { 
     'id' : 456, 
     'address' : '28 street name', 
     'city' : 'City Name', 
     'landmarks' : [ 
      { 
       'name' : 'landmark six', 
       'distanceInMiles' : 8.2 
      }, 
      { 
       'name' : 'landmark seven', 
       'distanceInMiles' : 1.6 
      } 
     ] 
    } 
] 

tôi đã có một số mã mà sẽ trả lại nhà có chứa một mốc đặc biệt, ví dụ lọc mảng này để trả về những ngôi nhà có cột mốc "mốc một" và tôi lưu trữ dữ liệu đã lọc đó vào một mảng riêng biệt. Nhưng bây giờ tôi muốn đi thêm một bước nữa và đặt hàng mảng kết quả đã lọc của tôi dựa trên giá trị distanceInMiles so với mốc được chọn. Vì vậy, gắn bó với bối cảnh này, tôi đang cố gắng viết một số mã sẽ trả về hai ngôi nhà với địa chỉ "22 tên phố" đầu tiên và ngôi nhà có tên "12 tên đường phố" thứ hai, vì "22 tên đường phố "ngôi nhà gần với mốc hơn cái kia.

Tôi đang sử dụng _loadash làm thư viện tiện ích của mình, nhưng cố gắng tìm hiểu cách sắp xếp mảng được lọc theo khoảng cách "một mốc". Bất kỳ ý tưởng?

Mọi trợ giúp sẽ được đánh giá cao.

+3

'r.sort (function (a, b) {return a.landmarks [0] .distanceInMiles - b.landmarks [0] .distanceInMiles;}) ' – dandavis

+2

@dandavis Bạn có thể đặt câu trả lời đó vào một câu trả lời và giải thích nó không. – dannypaz

Trả lời

0

var data = [ 
 
{ 
 
    "id" : 123, 
 
    "address" : "12 street name", 
 
    "city" : "City Name", 
 
    "landmarks" : [ 
 
    { 
 
    "name" : "landmark one", 
 
    "distanceInMiles" : 0.6 
 
    }, 
 
    { 
 
    "name" : "landmark two", 
 
    "distanceInMiles" : 0.4 
 
    } 
 
    ] 
 
}, 
 
{ 
 
    "id" : 345, 
 
    "address" : "22 street name", 
 
    "city" : "City Name", 
 
    "landmarks" : [ 
 
    { 
 
    "name" : "landmark one", 
 
    "distanceInMiles" : 0.2 
 
    }, 
 
    { 
 
    "name" : "landmark three", 
 
    "distanceInMiles" : 0.1 
 
    } 
 
    ] 
 
}, 
 
{ 
 
    "id" : 456, 
 
    "address" : "28 street name", 
 
    "city" : "City Name", 
 
    "landmarks" : [ 
 
    { 
 
    "name" : "landmark six", 
 
    "distanceInMiles" : 8.2 
 
    }, 
 
    { 
 
    "name" : "landmark seven", 
 
    "distanceInMiles" : 1.6 
 
    } 
 
    ] 
 
} 
 
]; 
 

 
function sortByLandmarkDistance(name) { 
 
    var getDistance = function(house) { 
 
     var minDistance = Infinity; 
 

 
     for(var i = 0; i < house.landmarks.length; ++i) 
 
      if(house.landmarks[i].name === name) 
 
      \t minDistance = Math.min(minDistance, house.landmarks[i].distanceInMiles); 
 

 
     return minDistance; 
 
    }; 
 

 
    return data.sort(function(a, b) { 
 
\t \t return getDistance(a) - getDistance(b); 
 
    }); 
 
} 
 
    
 
// Sort houses by distance from 'landmark one' 
 
var sorted = sortByLandmarkDistance('landmark one'); 
 
document.body.innerHTML = '<pre>' + JSON.stringify(sorted, null, ' ') + '</pre>';

+1

Cảm ơn, chỉ cần thử nghiệm tại địa phương và điều này là làm việc như tôi muốn nó. Rất cám ơn tất cả các câu trả lời khác, tôi chắc chắn họ cũng làm việc nhưng tôi đã không có cơ hội để đọc qua tất cả các câu trả lời đúng cách! Sự giúp đỡ của mọi người được đánh giá cao! –

+1

Việc triển khai này cho phép bạn quyết định mốc nào bạn muốn "sắp xếp theo", hầu hết các câu trả lời khác giả định nó là cái đầu tiên trong mảng '... mốc [0] ...' –

0

Sử dụng phương pháp array.sort với một chức năng tùy chỉnh phân loại. Sắp xếp sẽ hiển thị cho một số -1, 0 hoặc 1. Vì vậy, tất cả những gì bạn phải làm là trừ khoảng cách b từ a và viola!

function sortLandmarkDistanc1 (a, b) { 
    return a.landmarks[0].distanceInMiles - b.landmarks[0].distanceInMiles; 
} 
data.sort(sortLandmarkDistanc1); 

var data = [ 
 
\t \t { 
 
\t \t \t 'id' : 123, 
 
\t \t \t 'address' : '12 street name', 
 
\t \t \t 'city' : 'City Name', 
 
\t \t \t 'landmarks' : [ 
 
\t \t \t \t { 
 
\t \t \t \t \t 'name' : 'landmark one', 
 
\t \t \t \t \t 'distanceInMiles' : 0.6 
 
\t \t \t \t }, 
 
\t \t \t \t { 
 
\t \t \t \t \t 'name' : 'landmark two', 
 
\t \t \t \t \t 'distanceInMiles' : 0.4 
 
\t \t \t \t } 
 
\t \t \t ] 
 
\t \t }, 
 
\t \t { 
 
\t \t \t 'id' : 345, 
 
\t \t \t 'address' : '22 street name', 
 
\t \t \t 'city' : 'City Name', 
 
\t \t \t 'landmarks' : [ 
 
\t \t \t \t { 
 
\t \t \t \t \t 'name' : 'landmark one', 
 
\t \t \t \t \t 'distanceInMiles' : 0.2 
 
\t \t \t \t }, 
 
\t \t \t \t { 
 
\t \t \t \t \t 'name' : 'landmark three', 
 
\t \t \t \t \t 'distanceInMiles' : 0.1 
 
\t \t \t \t } 
 
\t \t \t ] 
 
\t \t }, 
 
\t \t { 
 
\t \t \t 'id' : 456, 
 
\t \t \t 'address' : '28 street name', 
 
\t \t \t 'city' : 'City Name', 
 
\t \t \t 'landmarks' : [ 
 
\t \t \t \t { 
 
\t \t \t \t \t 'name' : 'landmark six', 
 
\t \t \t \t \t 'distanceInMiles' : 8.2 
 
\t \t \t \t }, 
 
\t \t \t \t { 
 
\t \t \t \t \t 'name' : 'landmark seven', 
 
\t \t \t \t \t 'distanceInMiles' : 1.6 
 
\t \t \t \t } 
 
\t \t \t ] 
 
\t \t } 
 
\t ]; 
 

 
function sortLandmarkDistanc1 (a, b) { 
 
\t return a.landmarks[0].distanceInMiles - b.landmarks[0].distanceInMiles; 
 
} 
 
/* ignore this, just for showing results */ 
 
function repeatString(a,c){out="";for(var d=0;d<c;d++)out+=a;return out} 
 
function dump(a,c){c="number"!==typeof c?0:c;var d=typeof a,b=d;switch(d){case "number":case "boolean":b+=": "+a;break;case "string":b+="("+a.length+'): "'+a+'"';break;case "object":if(null===a)b="null";else if("[object Array]"===Object.prototype.toString.call(a)){b="array("+a.length+"): {\n";for(d=0;d<a.length;d++)b+=repeatString(" ",c)+" ["+d+"]: "+dump(a[d],"none",c+1)+"\n";b+=repeatString(" ",c)+"}"}else{sContents="{\n";cnt=0;for(var e in a)sContents+=repeatString(" ",c)+" "+e+": "+ 
 
dump(a[e],"none",c+1)+"\n",cnt++;sContents+=repeatString(" ",c)+"}";b+="("+cnt+"): "+sContents}}return b}; 
 
/*-----------------------*/ 
 
document.getElementById('before').innerHTML = dump(data); 
 
document.getElementById('after').innerHTML = dump(data.sort(sortLandmarkDistanc1));
<table> 
 
    <tbody> 
 
    <tr> 
 
     <td> 
 
<h1>Before</h1> 
 
<pre id="before"></pre> 
 
     </td> 
 
     <td> 
 
<h1>After</h1> 
 
<pre id="after"></pre> 
 
     </td> 
 
     </tr> 
 
    </tbody> 
 
    </table>

0

Có một khá nhiều ví dụ chính xác làm thế nào để làm điều này ở đây:

http://www.w3schools.com/jsref/jsref_sort.asp

Vì vậy, trong trường hợp của bạn, chức năng sẽ giống như thế này:

var data = getArrayFromAJAXHere(); 

data.sort(function(a,b){return a.landmarks[0].distanceInMiles - b.landmarks[0].distanceInMiles; }) 

Điều này sẽ sắp xếp mảng theo khoảng cách đến vị trí theo thứ tự tăng dần.

+0

bạn không bao giờ nên dựa vào trang web tồi tệ (w3schools). Sử dụng MDN thay thế: [Array.prototype.sort()] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) – Apolo

+0

@Apolo, tôi đã nghe điều này về chúng, nhưng dữ liệu chúng có trong trường hợp này có vẻ đúng khi tôi so sánh nó với MDN. Trường hợp cụ thể nơi trang web sai? – stubsthewizard

+0

hãy xem http://www.w3fools.com/ – Apolo

0

Tạo một mảng các giá trị được ghép nối với một mảng đếm chúng (ví dụ: [0, 1, 2, ...]). Code tôi cung cấp giả (đã lọc) mảng của bạn là định dạng này:

filtered = [ 
{ 
    id: 123, 
    address: "12 Street Name", 
    city: "City Name", 
    landmark: { 
     name: "landmark One" 
     //and other landmark properties 
    } 
}, { 
    id: 456, 
    //and so on... 

Code:

var content = []; 
var order = []; 
var x; 
for (x = 0; x < filtered.length; x++) { 
    content[x] = filtered[x].landmark.distanceInMiles; 
    order[x] = x; 
} 
var sorted = false; 
var y; 
while (!sorted) { 
    sorted = true; 
    for (x = 1; x < content.length; x++) { 
     if (content[x-1] > content[x]) { 
      sorted = false; 
      y = content[x]; 
      content[x] = content[x-1]; 
      content[x-1] = y; 
      y = order[x]; 
      order[x] = order[x-1]; 
      order[x-1] = y; 
     } 
    } 
} 

Bây giờ các mảng order nên chứa theo đúng thứ tự của những ngôi nhà, nhỏ nhất đến lớn nhất.

0

lọc và phân loại:

// first you call the filter function that will return a new filtered array 
var myFilteredAndSorteredArray = arr.filter(function(item) { 
    // here, you must return true if the item has the "landmark one" 
    // the map function returns a new array converting for what you're returning 
    // so, you return their names and use the indexOf to see if it has "landmark one" 
    return item.landmarks.map(function(land) { return land.name; }).indexOf("landmark one") > -1; 
}).sort(function(a, b) { 
    // now you sort the filtered array 
    // so, you use the same map function to get exactly the "landmark one" 
    var landA = a.landmarks[a.landmarks.map(function(land) { return land.name; }).indexOf("landmark one")]; 
    var landB = b.landmarks[b.landmarks.map(function(land) { return land.name; }).indexOf("landmark one")]; 
    // you always compare the second parameter with the first one 
    // since you want to return the smaller distance, you use the < operator 
    return landB.distanceInMiles < landA.distanceInMiles; 
})); 
0

Với lodash, bạn có thể sử dụng filter()sortBy() như một chuỗi:

_(data) 
    .filter(function(item) { 
     return _.any(item.landmarks, { 
      name: 'landmark one' 
     }); 
    }) 
    .sortBy(function(item) { 
     return _.find(item.landmarks, { 
      name: 'landmark one' 
     }).distanceInMiles; 
    }) 
    .value(); 
Các vấn đề liên quan