【问题标题】:Algorithm to split an array into N groups based on item index (should be something simple)根据项目索引将数组分成N组的算法(应该很简单)
【发布时间】:2008-11-26 22:38:35
【问题描述】:

我觉得应该是很简单明了的东西,只是卡在这个上面半个小时就走不动了。

我只需要根据元素索引将一个元素数组分成 N 个组。

例如,我们有一个包含 30 个元素 [e1,e2,...e30] 的数组,必须像这样分成 N=3 组:

group1: [e1, ..., e10]
group2: [e11, ..., e20]
group3: [e21, ..., e30]

我为 N=3 想出了像这样令人讨厌的混乱(伪语言,我在 0 和 1 上留下乘法只是为了澄清):

for(i=0;i<array_size;i++) {
   if(i>=0*(array_size/3) && i<1*(array_size/3) {
      print "group1";
   } else if(i>=1*(array_size/3) && i<2*(array_size/3) {
      print "group2";
   } else if(i>=2*(array_size/3) && i<3*(array_size/3)
      print "group3";
   }
}

但是正确的通用解决方案是什么?

谢谢。

【问题讨论】:

  • 从这个问题中得到的最重要的教训是边界条件、短(人为)期限和缺乏单元测试是致命的组合。
  • 你到底想做什么:分成 3 个较小的数组,或者打印“groupI” 30 次?

标签: algorithm arrays


【解决方案1】:

这样的事情呢?

for(i=0;i<array_size;i++) {
  print "group" + (Math.floor(i/(array_size/N)) + 1)
}

【讨论】:

  • 谢谢,最短的,没有额外的变量。
  • 令 array_size = 8 和 N = 3。由于整数数学给出 8/3 = 2,“3”组是 {0,1}、{2,3}、{3,4 }, {6,7}。
  • 是的,它应该是这样的:Math.floor(i/Math.ceil(array_size/N)) + 1
  • 如果您要像我一样索引一组值,请不要在最后加上 +1 :)
  • 在我看来,这并不能很好地将其分成几组。我做了一个demo。我会将拆分扩展到 [3,3,2,2,2] 而不是 [2,2,3,2,3]
【解决方案2】:

这里有一个小功能,可以满足您的需求 - 它假定您知道要创建的组数:

function arrayToGroups(source, groups) {  

                     //This is the array of groups to return:
                     var grouped = [];

                     //work out the size of the group
                     var groupSize = Math.ceil(source.length/groups);

                     //clone the source array so we can safely splice it (splicing modifies the array)
                     var queue = source.slice(0);

                     for (var r=0;r<groups;r++) {
                       //Grab the next groupful from the queue, and append it to the array of groups
                       grouped.push(queue.splice(0, groupSize));            
                     }       
             return grouped;
}

你会像这样使用它:

var herbs = ['basil', 'marjoram', 'aniseed', 'parsely', 'chives', 'sage', 'fennel', 'oregano', 'thyme', 'tarragon', 'rosemary'];

var herbGroups = arrayToGroups(herbs, 3);

返回:

herbGroups[0] = ['basil', 'marjoram', 'aniseed', 'parsely']
herbGroups[1] = ['chives', 'sage', 'fennel', 'oregano']
herbGroups[2] = ['thyme', 'tarragon', 'rosemary']

它不会进行任何完整性检查以确保您传入一个数组和一个数字,但您可以很容易地添加它。您也可以将其原型化为 Javascript 的对象类型,这将为您提供一个方便的数组上的“toGroups”方法。

【讨论】:

  • 我正在寻找一种方法来展开数组,我认为您对 splice 的使用很巧妙。 (实际用例是通过只允许数组的中间 API 传递一组坐标集)。
  • 谢谢,尼尔!很高兴能提供帮助 - 我完全忘记了这个。
【解决方案3】:

使用矢量语言使这项任务变得简单、正确的工具等等。只是想我会把它扔在那里让人们检查另一种方法。

K 中的解释版本(APL 后代):

split:{[values;n]    / define function split with two parameters
  enum:!n            / ! does enumerate from 0 through n exclusive, : is assign
  floor:_(#values)%n / 33 for this sample, % is divide, _ floor, # count
  cut:floor*enum     / 0 33 66 for this sample data, * multiplies atom * vector
  :cut _ values      / cut the values at the given cutpoints, yielding #cut lists
  }

values:1+!30           / generate values 1 through 30
n:3                    / how many groups to split into
groups:split[values;n] / set the groups

产生预期的输出:

(1 2 3 4 5 6 7 8 9 10
 11 12 13 14 15 16 17 18 19 20
 21 22 23 24 25 26 27 28 29 30)

K 中的简短版本:

split:{((_(#x)%y)*!y)_ x}
groups:split[1+!30;3]

产生相同的输出:

(1 2 3 4 5 6 7 8 9 10
 11 12 13 14 15 16 17 18 19 20
 21 22 23 24 25 26 27 28 29 30)

【讨论】:

  • 原创性和 cmets +1,希望我能给你 +10 验证输出!
【解决方案4】:

我在上面修改了Beejamin的功能,只是想分享一下。

function arrayToGroups($source, $pergroup) {  
    $grouped = array();
    $groupCount = ceil(count($source)/$pergroup);
    $queue = $source;
    for ($r=0; $r<$groupCount; $r++) {
        array_push($grouped, array_splice($queue, 0, $pergroup));    
    }       
    return $grouped;
}

这询问每组有多少个项目,而不是总共有多少组。 PHP。

【讨论】:

    【解决方案5】:
     const int g = 3;                      // number of groups
     const int n = (array_size + g - 1)/g; // elements per group
    
     for (i=0,j=1; i<array_size; ++i) {
        if (i > j*n)
            ++j;
         printf("Group %d\n", j);
     }
    

    【讨论】:

      【解决方案6】:
      int group[3][10];
      int groupIndex = 0;
      int itemIndex = 0;
      for(i = 0; i < array_size; i++)
      {
          group[groupIndex][itemIndex] = big_array[i];
          itemIndex++;
          if (itemIndex == 10)
          {
              itemIndex = 0;
              groupIndex++;   
          }
      }

      【讨论】:

        【解决方案7】:

        可能有无数种方法可以做到这一点。 我建议:为每个组创建一个基指针并计数。

        struct group {foo * ptr; size_t count };
        group * pgroups = new group [ngroups];
        size_t objects_per_group = array_size / ngroups;
        for (unsigned u = 0; u < ngroups; ++u ) {
           group & g =  pgroups[u];
           size_t index = u * objects_per_group;
           g.ptr = & array [index];
           g.count = min (objects_per_group, array_size - index);  // last group may have less!
        }
        ...`
        for (unsigned u = 0; u < ngroups; ++u) {
           // group "g" is an array at pgroups[g].ptr, dimension pgroups[g].count
           group & g =  pgroups[u];
           // enumerate the group:
           for (unsigned v = 0; v < g.count; ++v) {
              fprintf (stdout, "group %u, item %u, %s\n",
                 (unsigned) u, (unsigned) v, (const char *) g.ptr[v]->somestring);
        }  }
        
        delete[] pgroups;
        

        【讨论】:

          【解决方案8】:

          我认为问题有点复杂;并考虑到您只将组视为一维问题,您将对组的实际含义有一个非常奇怪的看法。

          首先,问题是根据组素数的数量以及您正在处理的组组合来确定维度的。在数学;这表示为 n 的 n 次方或 n^n 可以转换为 !n(n 的因数)。

          如果我有 5 个组排列为 (1, 2, 3, 4, 5),那么我想根据阶乘表达式将其表示为某些组或组的组合,那么组合会变大

          组 1x1 = 1,2,3,4,5
          2x1 组 = 12、23、45、13、14、15、21、24、25、31、32、34、35、41、42、43、45、51、52、53、54
          所以该策略创建了一个分支系统分支(很容易)
          12、13、14、15
          21、22、23、24
          31、32、34、35
          41、42、43、45
          51、52、53、55
          组 1 + 2x2x1 = (1, 23, 45), (2, 13, 45), (3, 12, 45), (4, 12, 35), (1, 24, 35), (1, 25, 35), (1, 32, 45), (1, 34, 25), (1, 35, 24), ...等

          正如您所见,当您开始添加阶乘集时,组合变得不那么容易创建数学参考来表达这些术语。当你进入一个长度大于 3 或 4 的基础组时,情况会变得更糟。

          如果我理解您的问题:您想用通用术语表达一种允许您以编程方式创建分组策略的算法?

          这是一个复杂的集合;并且在微积分中表现最好;作为集合论。否则你所做的只是一个二维数组处理。

          第一个Array表示分组策略; 第二个数组表示分组元素。

          我认为这不是您被要求做的,因为数学中的“GROUP”一词对该词有非常具体的分配。您不应该使用术语组;而是将其表示为一个集合; set1, set2 如果你正在这样做。

          Set1 包含 set2 的元素;因此,这是用与表达集合和联合相同的数学来处理的。查找“Vin Diagrams”和“Union”;除非您表示集合的因子,否则请避免使用术语组。
          http://en.wikipedia.org/wiki/Group_(mathematics)

          我认为您要表达的是已知集合或表中的组;这是在 wikipedia.org 示例 D2 上。

          在这种情况下,这意味着您必须像看魔方一样看待问题;它变得复杂。

          我在javascript中解决同样的问题;当我完成后,我可能会发布它;)。很复杂。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-09-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-03-03
            • 2011-11-29
            相关资源
            最近更新 更多