如何按嵌套数组中对象的值对数组进行排序

时间:2015-08-13 16:20:03

标签: javascript arrays sorting lodash

我正在尝试订购一个对象数组,在这个上下文中,我正在尝试编写一个函数,用户可以在距离地标的位置订购房屋数组。假设我从通过AJAX调用的API返回以下数据:

"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
            }
        ]
    }
]

我已经有一些代码会返回包含特定地标的房屋,例如过滤此数组以返回具有地标"标志性的"的房屋,并将过滤后的数据存储到单独的数组中。但我现在想更进一步,根据所选地标的distanceInMiles值对我过滤的结果数组进行排序。

所以,坚持这个背景,我正在尝试编写一些代码,这些代码将返回两个房子的地址" 22街道名称"首先和房子的#34; 12街道名称"地址第二,因为" 22街道名称"房子比其他房子更接近地标。

我使用_loadash作为我的实用程序库,但很难理解如何通过"具有里程碑意义的一个"距离。有什么想法吗?

非常感谢任何帮助。

6 个答案:

答案 0 :(得分: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)
            	minDistance = Math.min(minDistance, house.landmarks[i].distanceInMiles);

        return minDistance;
    };

    return data.sort(function(a, b) {
		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>';
&#13;
&#13;
&#13;

答案 1 :(得分:0)

使用array.sort方法和自定义排序功能。排序查找-101。所以你要做的就是从b和中提琴中减去距离a

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

&#13;
&#13;
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 sortLandmarkDistanc1 (a, b) {
	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));
&#13;
<table>
  <tbody>
    <tr>
      <td>
<h1>Before</h1>
<pre id="before"></pre>
        </td>
      <td>
<h1>After</h1>
<pre id="after"></pre>
        </td>
      </tr>
    </tbody>
  </table>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

这里有一个非常确切的示例:

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

因此,在您的情况下,函数看起来像这样:

var data = getArrayFromAJAXHere();

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

这将按照从位置到位置的顺序对数组进行排序。

答案 3 :(得分:0)

创建一个与数组配对的值数组(即[0, 1, 2, ...])。我提供的代码假设您的(已过滤)数组具有以下格式:

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

代码:

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;
        }
    }
}

现在数组order应该包含正确的房屋顺序,从最小到最大。

答案 4 :(得分:0)

过滤和排序:

// 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;
}));

答案 5 :(得分:0)

使用lodash,您可以使用filter()sortBy()作为链:

_(data)
    .filter(function(item) {
        return _.any(item.landmarks, {
            name: 'landmark one'
        });
    })
    .sortBy(function(item) {
        return _.find(item.landmarks, {
            name: 'landmark one'
        }).distanceInMiles;
    })
    .value();