在JavaScript中基于多个值特征重组多维数组?

时间:2016-04-09 08:58:43

标签: javascript arrays sorting multidimensional-array

我无法按照我希望的方式组织这些数据。在我的网页上,发生了一些我知道工作的事情......

  1. 一些PHP吐出一个多维关联数组。该数组的顶层是一个区域数组。每个区域都是一个时区阵列。
  2. 更多PHP创建了第二个多维关联数组。该数组的顶层是一个区域数组。每个区域都是UTC偏移数组。
  3. 两个数组都以相同的顺序从相同的数据生成。这意味着$offsets["region"][0]将基于与$timezones["region"][0]相同的时区。
  4. 两个数组都编码为JSON并传递给我的JavaScript。
  5. 我有以下JavaScript代码......

    var tempCurrentTimezoneArray = timezoneArray[ $("select[name='region_selector']").val() ];
      var tempCurrentOffsetArray = timezoneOffsetArray[ $("select[name='region_selector']").val() ];
      var groupedTimezones = {};
      var groupedOffsets = {};
      for (counter = 0; counter < tempCurrentOffsetArray.length; counter++) { 
        significantOffset = tempCurrentOffsetArray[counter].substr(tempCurrentOffsetArray[counter].length - 2);
        if (!(significantOffset in groupedTimezones)) {
          groupedTimezones[significantOffset] = [];
          groupedOffsets[significantOffset] = [];
        }
        groupedTimezones[significantOffset].push(tempCurrentTimezoneArray[counter]);
        groupedOffsets[significantOffset].push(tempCurrentOffsetArray[counter]);    
      }
      var offsetArray = [];
      for (var property in groupedTimezones) {
        if (!groupedTimezones.hasOwnProperty(property)) {
            continue;
        }
        groupedTimezones[property].sort();
        groupedOffsets[property].sort();
        offsetArray.push(parseInt(property));
      }
      offsetArray.sort();
      var currentTimezoneArray = [];
      var currentOffsetArray = [];
      for (counter = 0; counter < offsetArray.length; counter++) {
        currentTimezoneArray = currentTimezoneArray.concat(groupedTimezones[offsetArray[counter]]);
        currentOffsetArray = currentOffsetArray.concat(groupedOffsets[offsetArray[counter]]);
      }
    

    在前两行中,我删除了与页面上所选区域无关的所有时区数据。这意味着我留下了2个一维数组。任何一个数组的给定索引都直接与另一个数组相关。即....

    tempCurrentOffsetArray[0]是在tempCurrentTimezoneArray[0]找到的时区的UTC偏移量。

    本代码的其余部分旨在完成以下任务......

    1. 按UTC偏移量分组时区和偏移量。
    2. 按字母顺序组织每个偏移组。
    3. 创建两个数组,其中值首先按UTC偏移量组织,然后按字母顺序排列。
    4. 我遇到的问题是,在某些地区,我收到了几乎完美的列表,而在其他地区,我收到了一些看似随机数量的未定义值的列表,我不知道为什么。任何人都可以识别我的代码中的语法或逻辑错误吗?

      tempCurrentTimezoneArray输入数据here的JSON
      tempCurrentOffsetArray输入数据here

      的JSON

2 个答案:

答案 0 :(得分:2)

你认为还是太复杂了。将这两个数组保持同步是一团糟,最好将一个数组与对象一起使用。

var region_selector = $("select[name='region_selector']").val();
var tempCurrentTimezoneArray = timezoneArray[ region_selector ];
var tempCurrentOffsetArray = timezoneOffsetArray[ region_selector ];

//consolidate the Arrays
var data = [];  //create a new Array `data`
for(var i = tempCurrentOffsetArray.length; i--; ){
    //write into Array `data` at index `i` an object, containing these properties: 
    //`timezone`, `offset` and `offsetValue`, and their respective values
    data[i] = {
        timezone: tempCurrentTimezoneArray[i],
        offset: tempCurrentOffsetArray[i],
        //the + at the beginning converts the value behind that into a Number, like parseFloat() would do
        offsetValue: +tempCurrentOffsetArray[i].match(/^GMT([+-]\d+(?:\.\d+)?)$/)[1]
    }
}

//sorter-function for data to sort the values by offsetValue ASC first, then by timezone ASC
function sortedByOffset(a, b){
    return a.offsetValue - b.offsetValue || a.timezone.localeCompare(b.timezone);
}

//you should do this as late as possible, usually after the filtering
data.sort(sortedByOffset);

如果你坚持使用两个输出数组

var currentTimezoneArray = data.map(d => d.timezone);
var currentOffsetArray = data.map(d => d.offset);

否则这是非常灵活的

//utilities to fetch a property off the object
var getTimezone = d => d.timezone;
//aka function getTimezone(d){ return d.timezone }
var getOffset = d => d.offset;
//aka function getOffset(d){ return d.offset }

//example usages:
data.filter(d => d.offset === "GMT-5").map( getTimezone );
data.filter(d => d.offsetValue >= -2 && d.offsetValue <= -5 ).map( getOffset );

以第一个例子为例;根据SQL语句思考这将是

SELECT timezone FROM data WHERE offset = "GMT-5"

获取偏移量为GMT-5的每个条目的时区值

从一个包含所有值data的数组开始,然后通过过滤得到您感兴趣的子集(在这种情况下,每个条目,偏移量为&#34; GMT-5&#34;)。 / p>

现在你有一个数组,其中包含你所有的值,但仍然是整个对象;比如SELECT * FROM ...

map()函数在此子集中的每个条目上调用函数getTimezone(),并返回另一个仅包含时区值的数组。

第二个示例定义了过滤器的范围(从GMT-2到GMT-5的每个条目以及其间的每个GMT),并为这些条目返回偏移属性。

答案 1 :(得分:0)

我发现我的代码存在问题。实际上有三个问题第一个出现在第6行。在再次查看数据之后,我意识到某些值具有浮点整数或超过两位有效数字的偏移量。新的第6行是......

significantOffset = tempCurrentOffsetArray[counter].replace(/[^\d.-]/g, '');

我的代码的第二个问题也与解析浮点整数有关。在第21行,我们需要使用parseFloat而不是parseInt。新的第21行是......

offsetArray.push(parseFloat(property));

第三个问题在第23行。sort()需要被告知如何对整数进行排序。这是新的第23行......

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

最终代码看起来像这样......

var tempCurrentTimezoneArray = timezoneArray[ $("select[name='region_selector']").val() ];
    var tempCurrentOffsetArray = timezoneOffsetArray[ $("select[name='region_selector']").val() ];
    var groupedTimezones = {};
    var groupedOffsets = {};
    for (counter = 0; counter < tempCurrentOffsetArray.length; counter++) { 
      significantOffset = tempCurrentOffsetArray[counter].replace(/[^\d.-]/g, '');
      if (!(significantOffset in groupedTimezones)) {
    groupedTimezones[significantOffset] = [];
    groupedOffsets[significantOffset] = [];
      }
      groupedTimezones[significantOffset].push(tempCurrentTimezoneArray[counter]);
      groupedOffsets[significantOffset].push(tempCurrentOffsetArray[counter]);    
    }
    var offsetArray = [];
    for (var property in groupedTimezones) {
      if (!groupedTimezones.hasOwnProperty(property)) {
      continue;
      }
      groupedTimezones[property].sort();
      groupedOffsets[property].sort();
      offsetArray.push(parseFloat(property));
    }
    offsetArray.sort(function(a, b){return a-b});
    var currentTimezoneArray = [];
    var currentOffsetArray = [];
    for (counter = 0; counter < offsetArray.length; counter++) {
      currentTimezoneArray = currentTimezoneArray.concat(groupedTimezones[offsetArray[counter]]);
      currentOffsetArray = currentOffsetArray.concat(groupedOffsets[offsetArray[counter]]);
    }