【问题标题】:Javascript: Adding final element to array after for loop completesJavascript:for循环完成后将最终元素添加到数组
【发布时间】:2017-07-28 12:42:44
【问题描述】:

预期结果说明

我的来源是超过 30,000 行非常结构化的文本,前面的数字递增,后面的数字递增,并用冒号分隔。去掉非必需项,我留下了以下 sourceArray,为方便起见被截断:)

sourceArray = ["001:001", "001:002", "001:003", 
               "002:001", "002:002", 
               "003:001", "003:002"]; 

我正在尝试计算每个前数的后数并将其推送到数组中。在伪代码中,我的最终结果应该是这样的:

myArray[totalNumberOf_001_Items, totalNumberOf_002_Items, totalNumberOf_003_Items]

在我的简单示例中,最终值应该是:

[3, 2, 2]

问题和疑问

我的 for 循环在我的数据末尾结束,因此我的数组中缺少一个元素。

如何在循环中进行“额外的传递”,或者是否有其他方法可以将最终元素推送到我的数组?

var sourceArray = ["001:001", "001:002", "001:003",
  "002:001", "002:002",
  "003:001", "003:002"
];
var myArray = [];
var frontCounter = 1;
var backCounter = 1;

for (var i = 0; i < sourceArray.length; i++) {
  var text = sourceArray[i];
  var front = text.substr(0, 3);
  front = Number(front);
  var back = text.substr(4, 3);
  back = Number(back);

  if (front == frontCounter) {
    backCounter++;
  } else {
    myArray.push(backCounter - 1);
    backCounter = 2;
    frontCounter++;
  }
}
console.log(myArray); // result [3, 2]

【问题讨论】:

  • var i = 0; i &lt;= sourceArray.length; 我想添加一个='s ;这将在循环中添加一个额外的通道
  • 最终值不会是[3, 3, 1] 吗?
  • 从读到这里:“我正在尝试计算每个前面的数字有多少个后面的数字”我认为它会是 [3, 3, 1]
  • @JonathanPortorreal 和 = ,额外的循环导致 sourceArray[i] 变为 undefined
  • @DulyKinsky 循环 1:myArray = [1],循环 2:myArray = [2],循环 3:myArray = [3] 符合预期。然后循环 4 出现并跳到 else 语句。 myArray = [3] 和以前一样。作为补偿,backCounter 被重置为 2。循环 5:myArray = [3, 2]。这是一个非常简化的例子。由于我的实际数据仅限于 5 个前面的数字,我最终得到的结果更像 [31, 25, 21, 26]。但是没有将最终元素推送到数组。

标签: javascript arrays for-loop


【解决方案1】:

您可以使用如下所示的对象来跟踪一段文本出现的次数,文本将是键,值是它们出现的次数。从中你可以构建你的数组

var sourceArray = ["001:001", "001:002", "001:003", 
                   "002:001", "002:002", 
                   "003:001", "003:002"]; 

var frontEncounters = {};

function updateFrontEncounters(frontEncounters, front){
    var keys = Object.keys(frontEncounters);
    if(keys.indexOf(front) == -1)
    {
        frontEncounters[front] = 1;
    }
    else
    {
        frontEncounters[front] += 1;
    }
}

for(var item in sourceArray){
    var text = sourceArray[item];
    var front = text.substr(0, 3);
    var back = text.substr(4, 3);
    updateFrontEncounters(frontEncounters, front);  
}

var keys = Object.keys(frontEncounters);
var myArr = [];

for(var key in keys)
{
    myArr.push(frontEncounters[keys[key]])
}
console.log(myArr);

【讨论】:

    【解决方案2】:

    使用一个对象来存储“前”数字及其计数。

    for (var i = 0; i < sourceArray.length; i++) {
        var num = sourceArray[i].slice(0,3);
        counts[num] = counts[num] ? counts[num]+1 : 1;
    }
    

    完成后,您可以非常轻松地将其转换为数组:

    var result = Object.keys(counts).map(function (key) {
        return counts[key];
    });
    

    有了 ES-2017,就更简单了:

    var result = Object.values(counts)
    

    工作片段

    var sourceArray = ["001:001", "001:002", "001:003", 
                       "002:001", "002:002", 
                       "003:001", "003:002"]; 
    var counts = {};
    
    for (var i = 0; i < sourceArray.length; i++) {
        var num = sourceArray[i].slice(0,3);
        counts[num] = counts[num] ? counts[num]+1 : 1;
    }
    console.log(counts);
    var result = Object.keys(counts).map(function (key) {
        return counts[key];
    });
    console.log(result);
    
    // ES-2017
    //console.log(Object.values(counts));

    【讨论】:

    • 这似乎有效,因为我能够编译一个具有正确长度的嵌套数组的主数组。但是,它们似乎并不总是按严格的顺序排列。
    • @BrianWilson:是的。不保证数组是有序的。这就是为什么一个对象(如果您有多个来源,则为一个对象数组)对您来说是一个更好的选择,因为它允许您查询键并且您一定会拥有与相关联的值键。
    【解决方案3】:

    这是您可以使用的替代方法,这样您就不必遍历行的整个源代码 (30,000) 。使用 while 循环,以便在到达 0 时立即中断;使用Map 来存储唯一编号,方法是将索引/frontnumber 设为key,并将其value 设为用作计数器以跟踪其总数的对象。如果key存在,更新总数;如果没有,则创建一个新的计数器对象。然后只需返回Map,通过map'将其转换为所需的数组,将其转换为仅包含总数的数组。

    var sourceArray = ["001:001", "001:002", "001:003",
      "002:001", "002:002",
      "003:001", "003:002"
    ];
    
    function getTotal(sourceArray) {
    
      let count = new Map();
      let update = item => count.get(item).total++;
      let create = item => count.set(item, {total: 1});
    
      const getItem = index => {
        let text = sourceArray[index];
        return text.substr(0, 3);
      }
    
      let index = -1;
      let start = 0;
      
      while (index != 0 && start < sourceArray.length) {
        index = getItem(start++);
        count.has(index) ? update(index) : create(index);
      }
    
      return [...count.values()].map(item => item.total);
    }
    
    console.log(getTotal(sourceArray));

    【讨论】:

    • 谢谢。这确实解决了问题。但是,它会创建一个新的:)。我需要的答案是 [3, 2, 2]。当我用完新的前数字时,循环应该结束。我不能有任何 0 元素。特别是因为我的数据有 30,000 多个项目。它会产生数千个额外的元素。
    • @BrianWilson 因此,如果说数字 2 有 0 个元素,3 有 3 个元素,那么[3,0,2] 会是这样吗?您可以过滤掉0,但您将失去与索引关联的值的概念。
    • [3, 0, 3] 永远不可能。只有正整数。
    • @BrianWilson 我已经更新了代码以满足新的需求
    猜你喜欢
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2019-09-09
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多