【问题标题】:Reorganizing multidimensional arrays based on multiple value characteristics in JavaScript?基于 JavaScript 中的多个值特征重组多维数组?
【发布时间】:2016-04-09 08:58:43
【问题描述】:

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

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

我有以下 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 偏移量排列,其次按字母顺序排列。

我遇到的问题是,在某些地区我收到了几乎完美的列表,而在其他地区我收到了一些看似随机数量的未定义值的列表,我不知道为什么。任何人都可以识别我的代码中的语法或逻辑错误吗?

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

【问题讨论】:

  • 请添加一些数据示例。
  • @NinaScholz 添加了指向传递给此脚本的实际数据的 JSON 编码版本的链接。
  • 我使用示例数据运行了您的代码,但在结果数组中看不到任何未定义的值。我可以看到一个可能的错误映射,其中处理了 0.5 的偏移量,但就是这样。您能否准确指定您看到未定义值的偏移量或区域?

标签: javascript arrays sorting multidimensional-array


【解决方案1】:

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

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 的数组开始,然后通过过滤获得您感兴趣的子集(在本例中为每个条目,偏移量为“GMT-5”)。

现在你有了一个包含所有你感兴趣的值的数组,但仍然是整个对象;像SELECT * FROM ...

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

第二个示例为过滤器定义了一个范围(从 GMT-2 到(包括 GMT-5 以及介于两者之间的每个 GMT)的每个条目)并为这些条目返回偏移属性。

【讨论】:

  • 我对 JavaScript 还是很陌生。您能否为实现此结果所使用的逻辑和功能添加更多解释?
  • 您甚至可以将“区域”包含在数据对象中,并使其成为另一个过滤器;只是作为旁注。 您特别需要解释什么? 逻辑很简单:一个大数组,其中包含每一行(索引)的对象和每一列的属性,就像您想象的 Excel 表一样。然后添加过滤器,按任何排序,并映射您实际想要的数据;也许是一列(比如时区或偏移量),也许你想以某种方式处理这个值,比如将时区和偏移量连接成一个字符串,...
  • 过滤是我有点困惑的地方。我可以自己查找所有其他功能,但我似乎无法在网上找到关于“=>”在这种情况下的含义的答案。
  • 或者您是否对 lambda 表达式感到困惑,或者将函数分配给变量或将它们传递给其他函数?好吧,例如,lambdas: d =&gt; d.timezone 只是 function(d){ return d.timezone } 的简写,该函数需要一个对象 d 并返回该对象的属性 timezone。而另一部分,是的,您可以创建对函数的引用并像 JS 中的任何其他值一样传递它
  • @Allenph, d =&gt; d.offset === "GMT-5" 例如只是 function(d){ return d.offset === "GMT-5" } 的简写,此函数在数据数组的每个条目上调用,并返回一个新数组,其中包含过滤器所在的所有条目函数返回一个真值。 (0, NaN, empty-string, null, undefined, false) 是假值(解析为假;例如在条件下),其他所有值都是真
【解决方案2】:

我发现我的代码存在问题。实际上存在三个问题,第一个问题出现在第 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]]);
    }

【讨论】:

    猜你喜欢
    • 2021-07-06
    • 2017-05-19
    • 2018-05-25
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 2019-02-15
    相关资源
    最近更新 更多