2013-01-01 193 views
3

我有两个阵列。第一个包含地点和一些关于它们的信息。这是一个三维的多维数组:从另一个阵列创建一个新阵列

  • 第1步:类别(例如标题,日期等...)。
  • 步骤2:将实际的地方
  • 步骤3:纬度和经度(下的类别坐标)

    places[0][0] = 'Stockholm';  // Header 
    places[0][1] = 'Karlstad'; 
    places[0][2] = 'Borgholm'; 
    places[1][0] = '2012-05-25'; // Date 
    places[1][1] = '2012-06-12';  
    places[1][2] = '2012-05-14' 
    places[2][0] = 'Lorum ipsum lorum ipsum lorum ipsum';  // Description 
    places[2][1] = 'Ipsum lorum lorum ipsum lorum ipsum'; 
    places[2][2] = 'Forum Lorum Porum'; 
    places[3][0][0] = '56,123342';  // Latitude 
    places[3][0][1] = '49,123123';  // Longitude 
    places[3][1][0] = '23,543231'; 
    places[3][1][1] = '45,955432'; 
    places[3][2][0] = '34,123459'; 
    places[3][2][1] = '45,325198'; 
    ...and so on... 
    

第二数组包含搜索结果的,相匹配的搜索,即地。我想要做的是在第一个数组中创建一个包含 的新数组,但仅限于第二个数组中的元素(所以在上面的示例中,只有place [1]('Karlstad')应该在 新的数组。

我也希望新的阵列有一个新的结构,而是在第一级类别的我想在第一级别的地方(以下SE例子)。

results = [1, 15, 17, 19, 32, 91, 102, 103]; 

newPlaces[0][0] = 'Karlstad'; 
newPlaces[1][0] = 'Kalmar'; 
newPlaces[2][0] = 'Luleå'; 
newPlaces[3][0] = 'Överkalix'; 
newPlaces[4][0] = 'Malmö'; 
newPlaces[5][0] = 'Ystad'; 
newPlaces[6][0] = 'Linköping' 
...and so on... 

会是什么是最好和最简单的方法来做到这一点? 我想我应该使用一个for循环,如下所示(这是行不通的)?

for (var i = 0; i < results.length; i++) { 
    newPlaces[i][0] = places[0][results[i]]; 
    newPlaces[i][1] = places[1][results[i]]; 
    newPlaces[i][2] = places[2][results[i]]; 
    newPlaces[i][3] = places[3][results[i]]; 
} 

非常感谢!

+3

你真的应该真的真的使用JSON这种东西,它会更容易为机器和人。您可以轻松将其转换为JSON,反之亦然。 –

+1

+1给@ Wololo的建议。通过使用JSON和/或JS对象,这种类型的东西变得更加可读。 – hayavuk

回答

4

要添加到@李维斯的回答,您还可以使用ES5地图:

使用本机Array.prototype.map:

newPlaces = results.map(function(result) { 
    return [ 
     places[0][result], 
     places[1][result], 
     places[2][result], 
     places[3][result] 
    ]; 
}); 

使用手工制作的地图:

感谢以下Marcus的评论,指出原生地图的性能问题。

很明显,这是一个自定义版本的map,它掩盖了for循环。到目前为止,它似乎没有简单地使用for循环好得多,但我没有解释为什么,也没有真正重要。

// Custom map function 
function map(arr, func) { 
    var newArr = []; 
    var cnt = arr.length; 
    var arrLen = arr.length; 
    for (; cnt; cnt--) { 
     newArr.push(func(arr[arrLen - cnt]));  
    } 
    return newArr; 
} 

newPlaces = map(results, function(result) { 
    return [ 
     places[0][result], 
     places[1][result], 
     places[2][result], 
     places[3][result] 
    ]; 
}); 

很明显,代码仍然像使用本地地图一样干净,但性能提高了十倍。它的速度也比for循环快得多。

下面是使用各种方法执行1M迭代小提琴:

http://jsfiddle.net/6wArq/3/

编辑:

顺便说一下,浏览器是如此古老,他们甚至没有Array.prototype.map,你可以使用ES5 shim添加此功能。

EDIT2:

退房的documentationArray.prototype.map上MDN。

EDIT3:

好,自定义地图是不确凿比循环更快,所以我们说,它执行一样好。

EDIT4:

的自定义地图的最终版本,使得它一直执行比一般的for循环,其计数器增加得更快。我假设递减计数器的for循环会执行和最终自定义映射函数一样的效果。

+0

使用'.map'完全不错,但[与内联for循环相比,性能可怕](http://jsperf.com/eam-map-vs-for-loop)(〜%80比我慢系统),所以我反对在这个特定情况下使用这种方法。 – mekwall

+1

@MarcusEkwall:我已经更新了包含地图的自定义版本的答案,该版本比for循环更好。 ;) – hayavuk

+0

@bvukleic不错!原生的Array.map比JS实现要慢,这很愚蠢。哦,当引擎优化突破使用C绑定的开销时(这与PCRE发生的情况相同),会发生这种情况。太糟糕的回归测试没有考虑到性能提升,例如这些;) – mekwall

2

对于给定的多维结构,for循环可能是最简单的。你只需要声明你的变量,并添加一些简写以便于阅读代码。这应该这样做:

var newPlaces = []; 
for (var i = 0; i < results.length; i++) { 
    var id = results[i] 
    newPlaces[i] = [ 
     places[0][id], 
     places[1][id], 
     places[2][id], 
     places[3][id], 
     places[4][id] 
    ]; 
} 

既然你这个标记与jQuery,这里是你如何使用jQuery.each使你的代码稍微简单(但不作为高性能>慢90%,如通过@Marcus Ekwall提及):

var newPlaces = []; 
$.each(results, function(i, id) { 
    newPlaces[i] = [ 
     places[0][id], 
     places[1][id], 
     places[2][id], 
     places[3][id], 
     places[4][id] 
    ]; 
}); 

重要时请记住性能。 jQuery非常方便,并且允许您更快速/更容易地编写代码,但如果您不小心,它可能会减慢您的网站/应用程序。

+3

以上是[测试用例](http://jsfiddle.net/mekwall/R49YL/)。 @Levi必须在我面前回答,所以我不会再添加其他答案。 – mekwall

+1

不要使用'.each'作为嵌入式for循环的直接替换。可读性的微小增长(在这种情况下)不值得巨大的性能下降。我们在这里谈论[约慢90%](http://jsperf.com/jquery-each-vs-for-loop):) – mekwall

+0

我完全同意Marcus,在大多数情况下,包括这一个(因为我们没有知道我们正在合作多少个地方)。但是,当我知道我正在处理一个小数据集时,便利性和可读性通常对我来说是值得的。 – Levi

1

如何:

var places = [ ]; 

... 

var newPlaces = [ ]; 
var placesArray; 

for (var i = 0; i < places[0].length; i++) // loop through the headers first 
{ 
    placesArray = [ ]; 

    for (var j = 0; j < places.length; j++) // make sure we loop through the other properties too 
    { 
    placesArray.push(
     places[j][i] 
    ); 
    } 

    newPlaces.push(
    placesArray 
); 
} 

console.log(places, placesArray); 

至少这样你不局限于但是大的阵列。

0

我怀疑为什么你可能有这个困难的原因在于你滥用数组。很简单,这是在这里使用的不正确的数据结构。这些信息可以在逻辑上由JSON表示。

var places = [ 
    { 
     "Header": "Stockholm", 
     "Date": "2012-05-25", 
     "Description": "Lorum ipsum lorum ipsum lorum ipsum", 
     "Latitude": "56,123342", 
     "Longitude": "49,123123" 
    }, 
    { 
     "Header": "Karlstad", 
     "Date": "2012-06-12", 
     "Description": "Lorum ipsum lorum ipsum lorum ipsum", 
     "Latitude": "23,543231", 
     "Longitude": "45,955432" 
    } 
];​ 

那么你for循环是微不足道的:

var newPlaces = []; 
for (var i = 0; i < results.length; i++) { 
    newPlaces[i] = places[results[i]]; 
} 

这将产生相同的形式上面的地方对象的简单集合。