2008-11-26 27 views
3

我觉得它应该是非常简单明显的东西,但是在最后半个小时内就停留在这一点上,无法继续前进。根据项目索引将数组拆分为N组的算法

我需要的是根据元素索引将一组元素分成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"; 
    } 
} 

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

谢谢。

+0

这个问题最重要的一个教训是,边界条件,短的(人为的)期限和缺乏单元测试是一个致命的组合。 – 2008-11-27 02:23:47

+1

你到底想做什么:分成3个小阵列,或打印“groupI”30次? – blabla999 2009-01-13 20:35:02

回答

8

什么这样的事情?

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

谢谢,最短的一个,没有额外的变量。 – serg 2008-11-26 22:54:37

+0

设array_size = 8且N = 3。由于整数数学给出8/3 = 2,所以“3”组为{0,1},{2,3},{3,4},{6,7} 。 – 2008-11-27 02:19:48

1
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); 
} 
1
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++; 
    } 
}
1

这可能有无数的方法。 我会建议:对于每个组,创建一个基指针并计数。

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; 
1

使用矢量语言使得这个任务变得简单,正确的工具和所有这些。只是想我会把它扔到那里让人们检查一种替代方法。

的在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) 
0

我觉得问题有点复杂;并且考虑到你只将组看作一维问题,你会对组的实际情况产生非常奇怪的看法。

首先,问题是根据组素数的数量以及您正在处理的组合。数学;这被表示为能够被翻译成n(n的因子)的n或n^n的幂。

如果我已经5组排列为(1,2,3,4,5),那么我想它表示为某些组或根据阶乘表达式组combonations则combonations得到更大

组的1x1 = 1,2,3,4,5
组2×1 = 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
(1,12,45),(2,13,45),(3,12,45),(4),(2,13,45),(3,12,45),(4,14,15,16,17,18,19,20,21,22,24,25,25,27,27,27,27,28,29) ,12,35),(1,24,35),(1,25,35),(1,32,45),(1,34,25),(1,35,24),...等

当你开始添加因子,你可以看到设置comboniations变得不那么容易创建的数学参考表达的条款。当你进入长度大于3或4的基座时,情况会变得更糟。

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

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

第一阵列表达分组策略; 第二个数组表示分组元素。

我不认为这是你被要求做什么,因为在数学术语“基”的术语一个非常具体的分配。你不应该使用术语组;而是将其表达为一组; set1,set2,如果这是你在做什么。

SET1包含SET2的元素;因此,这与数据处理的集合和联合表达式相同。查找“Vin Diagrams”和“Union”;避免使用术语组,除非你代表一个组的因素。
http://en.wikipedia.org/wiki/Group_(mathematics)

我觉得你想要表达的是已知组或表中的组;这在wikipedia.org示例D2上。

在这种情况下,这意味着你必须看像一个魔方的问题;并且变得复杂。

我的工作在JavaScript同样的问题;当我完成我可能会发布它;)。这非常复杂。

3

这里有一个小功能,将你想要做什么 - 它假定你知道的组数你想:

function arrayToGroups(source, groups) { 

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

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

        //clone the source array so we can safely splice it 
        var queue = source; 

        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”方法。

2

我修改了上面的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。