如何对运行时指定的数组维度求和?

发布于 2024-07-04 11:05:49 字数 1250 浏览 7 评论 0原文

我正在研究一个函数来建立分布的熵。 它使用系词(如果有熟悉的话)。 我需要根据“关心”的维度来总结数组中的值。

示例:考虑以下示例...

Dimension 0 (across)
_ _ _ _ _ _ _ _ _ _ _ _ _
|_ 0 _|_ 0 _|_ 0 _|_ 2 _|  Dimension 1
|_ 1 _|_ 0 _|_ 2 _|_ 0 _|   (down)
|_ 0 _|_ 3 _|_ 0 _|_ 6 _|
|_ 0 _|_ 0 _|_ 0 _|_ 0 _|

I "care about" dimension 0 only, and "don't care" about the rest (dim 1).
Summing this array with the above specifications will
"collapse" the "stacks" of dimension 1 down to a single 4 x 1 array:

_ _ _ _ _ _ _ _ _ _ _ _ _ 
|_ 1 _|_ 3 _|_ 2 _|_ 8 _|

This can then be summed, or have any operation performed.

我需要使用“n”维数组来执行此操作,该数组可能为 20。此外,我需要能够执行此操作,关心某些维度并折叠其余维度。 我在这方面遇到了特别困难,因为我无法想象 20 个维度:p。 如果有人可以帮助我设置一些 c/c++ 代码来折叠/求和,我将非常感激。

更新:

刚到家。 这里有一些信息可以回答您的问题:

  1. 抱歉回滚编辑,我希望当我单击回滚时它会向我显示更改,以便我可以看到我搞砸的内容,有点像维基百科。 据我发现,情况并非如此。
  2. @jeff - 什么没有意义? 我使用这项出色的服务(我认为是)有正当理由。 我想在我的爱好上做得更好,仅此而已,就像我在高中时一样。 我的许多帖子都涉及实现遗传算法(这篇文章,稀疏数组,排列数组,指针操作)。
  3. 我使用稀疏数组表示,因为使用传统(密集)数组可能会超过宇宙中的分子数量。 目前,稀疏数组本身的实现并不重要,因为我正在努力使其在使用稀疏表示之前与标准数组一起使用。 对于那些没有看过我之前的问题的人,我使用二叉搜索树作为包含稀疏数组点的结构,并使用“驱动程序”函数根据需要遍历树,返回该函数设计的任何功能。 这是灵活的,因此我可以适应许多不同的访问数组的方法。
  4. 该结构是一个超立方体,维数以及每个维度的长度在运行时指定(它们都是相同的,因为它是一个超立方体)。

感谢大家的贡献。

I am working on a function to establish the entropy of a distribution. It uses a copula, if any are familiar with that. I need to sum up the values in the array based on which dimensions are "cared about."

Example: Consider the following example...

Dimension 0 (across)
_ _ _ _ _ _ _ _ _ _ _ _ _
|_ 0 _|_ 0 _|_ 0 _|_ 2 _|  Dimension 1
|_ 1 _|_ 0 _|_ 2 _|_ 0 _|   (down)
|_ 0 _|_ 3 _|_ 0 _|_ 6 _|
|_ 0 _|_ 0 _|_ 0 _|_ 0 _|

I "care about" dimension 0 only, and "don't care" about the rest (dim 1).
Summing this array with the above specifications will
"collapse" the "stacks" of dimension 1 down to a single 4 x 1 array:

_ _ _ _ _ _ _ _ _ _ _ _ _ 
|_ 1 _|_ 3 _|_ 2 _|_ 8 _|

This can then be summed, or have any operation performed.

I need to do this with an array of 'n' dimensions, which could feasibly be 20. Also, I need to be able to do this, caring about certain dimensions, and collapsing the rest. I am having an especially hard time with this because I cant visualize 20 dimensions :p . If anyone could help me set up some c/c++ code to collapse/sum, I would be very very grateful.

Update:

Just got home. Here is some info to answer your questions:

  1. Sorry for rolling back the edits, I was hoping when I clicked roll-back it would show me the changes so I could see what I messed up, a bit like wikipedia. This wasn't the case, as I found out.
  2. @jeff - What doesnt make sense? I am using this great service for (what I think is) a legit reason. I want to get better at my hobby, which is all it is, as I am in high school. Many of my posts regard implementing a genetic algorithm (This post, sparsearray, rank an array, pointer manipulation).
  3. I am using a sparse array representation, as it is possible to exceed the number of molecules in the universe using a traditional (dense) array. For now, the implementation of the sparsearray itself doesnt matter a whole lot, as I am working to make it work with a standard array before going to a sparse representation. For those who havent seen my previous questions, I am using a binary search tree as the structure to contain the sparse array points, and a "driver" function to traverse the tree as necessary, returning whatever the function is designed to do. This is flexible, so I can accomodate a lot of different methods of accessing the array.
  4. The structure is a hypercube, and the number of dimensions is specified at run time, as well as the length of each dimension (which are all the same, as it is a hypercube).

Thanks everyone for your imput.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

美胚控场 2024-07-11 11:05:49

这可能有应用。 假设您实现了 2D Conway 的生命游戏(定义了 2D 平面,1 表示“活着”,0 表示“死亡”),并且存储了每次迭代的游戏历史记录(然后定义了 3D 立方体)。 如果您想知道历史上有多少活细菌,您可以使用上述算法。 您可以对生命游戏网格的 3D(以及 4D、5D 等)版本使用相同的算法。

我想说这是一个递归问题,我还不是 C 程序员,但我知道在 C 中这是可能的。在 python 中,


def iter_arr(array):
  sum = 0
  for i in array:
    if type(i) == type(list()):
      sum = sum + iter_arr(i)
    else:
      sum = sum + i
  return sum 
  1. 迭代数组中的每个元素
  2. 如果元素是另一个数组,则再次调用该函数
  3. 如果元素是不是数组,将其添加到总和中
  4. 返回总和

然后您可以将其应用于“关心”维度中的每个元素。

不过,由于鸭子类型,这在 python 中更容易......

This could have applications. Lets say you implemented a 2D Conway's Game of Life (which defines a 2D plane, 1 for 'alive', 0 for 'dead') and you stored the Games history for every iteration (which then defines a 3D cube). If you wanted to know how many bacteria there was alive over history, you would use the above algorithm. You could use the same algorithm for a 3D, (and 4D, 5D etc.) version of Game of Life grid.

I'd say this was a question for recursion, I'm not yet a C programmer but I know it is possible in C. In python,


def iter_arr(array):
  sum = 0
  for i in array:
    if type(i) == type(list()):
      sum = sum + iter_arr(i)
    else:
      sum = sum + i
  return sum 
  1. Iterate over each element in array
  2. If element is another array, call the function again
  3. If element is not array, add it to the sum
  4. Return sum

You would then apply this to each element in the 'cared about' dimension.

This is easier in python due to duck-typing though ...

是你 2024-07-11 11:05:49

@Jeff

我实际上认为这是一个有趣的问题。 我不确定它有多大用处,但这是一个有效的问题。

@Ed

你能提供更多关于这个问题的信息吗? 你说数组的维度是动态的,那么元素的数量也是动态的吗?

编辑:无论如何我都会尝试回答这个问题。 我无法直接给你代码(在这台电脑上没有任何编译器的情况下需要一段时间才能得到它),但我可以给你指出正确的方向......

让我们使用 8 维( 0-7),以索引0到3为例。 您只关心 1,2 和 6。这意味着您有两个数组。 首先,array_care[4][4][4] 用于 1,2 和 6。array_care[4][4][4] 将保存最终结果。

接下来,我们想以一种非常具体的方式进行迭代。 我们有数组 input[4][4][4][4][4][4][4][4] 来解析,我们关心维度 1、2 和6.

我们需要定义一些临时索引:

int dim[8] = {0,0,0,0,0,0,0,0};

我们还需要存储我们想要增加索引的顺序:

int increase_index_order[8] = {7,5,4,3,0,6,2,1};
int i = 0;

这个顺序对于执行您请求的操作很重要。

定义终止标志:

bool terminate=false;

现在我们可以创建循环:

while (terminate)
{
array_care[dim[1]][dim[2]][dim[6]] += input[dim[0]][dim[1]][dim[2]][dim[3]][dim[4]][dim[5]][dim[6]][dim[7]];

while ((dim[increase_index_order[i]] = 3) && (i < 8))
{
dim[increase_index_order[i]]=0;
i++;
}

if (i < 8) {
dim[increase_index_order[i]]++; i=0;
} else {
terminate=true;
}
}

这应该适用于 8 维,关心 3 维。 让它变得动态需要更多的时间,而我没有时间。 希望这可以帮助。 我很抱歉,但我还没有学会代码标记。 :(

@Jeff

I actually think this is an interesting question. I'm not sure how useful it is, but it is a valid question.

@Ed

Can you provide a little more info on this question? You said the dimension of the array is dynamic, but is the number of elements dynamic as well?

EDIT: I'm going to try and answer the question anyways. I can't give you the code off the top of my head (it would take a while to get it right without any compiler here on this PC), but I can point you in the right direction ...

Let's use 8 dimensions (0-7) with indexes 0 to 3 as an example. You care about only 1,2 and 6. This means you have two arrays. First, array_care[4][4][4] for 1,2, and 6. The array_care[4][4][4] will hold the end result.

Next, we want to iterate in a very specific way. We have the array input[4][4][4][4][4][4][4][4] to parse through, and we care about dimensions 1, 2, and 6.

We need to define some temporary indexes:

int dim[8] = {0,0,0,0,0,0,0,0};

We also need to store the order in which we want to increase the indexes:

int increase_index_order[8] = {7,5,4,3,0,6,2,1};
int i = 0;

This order is important for doing what you requested.

Define a termination flag:

bool terminate=false;

Now we can create our loop:

while (terminate)
{
array_care[dim[1]][dim[2]][dim[6]] += input[dim[0]][dim[1]][dim[2]][dim[3]][dim[4]][dim[5]][dim[6]][dim[7]];

while ((dim[increase_index_order[i]] = 3) && (i < 8))
{
dim[increase_index_order[i]]=0;
i++;
}

if (i < 8) {
dim[increase_index_order[i]]++; i=0;
} else {
terminate=true;
}
}

That should work for 8 dimensions, caring about 3 dimensions. It would take a bit more time to make it dynamic, and I don't have the time. Hope this helps. I apologize, but I haven't learned the code markups yet. :(

滥情稳全场 2024-07-11 11:05:49

我不敢苟同,总是有另一种方法..

如果你真的不能重构,那么你需要将问题分解成更小的部分..就像我说的,确定你需要求和的维度,然后一次打一个。.

另外,停止更改编辑,他们正在纠正您的拼写错误,他们正在努力帮助您;)

I beg to differ, there is ALWAYS another way..

And if you really cannot refactor, then you need to break the problem down into smaller parts.. Like I said, establish which dimensions you need to sum, then hit them one at a time..

Also, stop changing the edits, they are correcting your spelling errors, they are trying to help you ;)

久伴你 2024-07-11 11:05:49

我认为这里要做的最好的事情是两件事之一/两者:

  1. 重新思考设计,如果它太复杂,找到一种不太复杂的方法。
  2. 停止尝试将其可视化。:P 只需存储需要求和的相关维度,然后一次进行一个计算。 一旦有了基本代码,就可以考虑提高算法的效率。

I think the best thing to do here would be one/both of two things:

  1. Rethink the design, if its too complex, find a less-complex way.
  2. Stop trying to visualise it.. :P Just store the dimensions in question that you need to sum, then do them one at a time. Once you have the base code, then look at improving the efficiency of your algorithm.
合约呢 2024-07-11 11:05:49

实际上,通过折叠列,您已经对它们进行了求和,因此对于您的示例来说,维度根本不重要。 我错过了什么还是你错过了什么?

Actually, by colllapsing the colums you already summed them, so the dimension doesn't matter at all for your example. Did I miss something or did you?

夏天碎花小短裙 2024-07-11 11:05:49

如果我理解正确的话,您想要将沿 1 维的每个“bin”定义的横截面中的所有值相加。 我建议为您的目的地创建一个一维数组,然后循环遍历数组中的每个元素,将值与感兴趣维度的索引添加到目的地。

如果您使用任意数量的维度,则必须有一种寻址元素的方法(我很好奇您是如何实现这一点的)。 您对此的实现将影响您设置目标索引的方式。 但一个明显的方法是在迭代循环中检查 if 语句。

If I understand correctly, you want to sum all values in the cross section defined at each "bin" along 1 dimension. I suggest making a 1D array for your destination, then looping through each element in your array adding the value to the destination with the index of the dimension of interest.

If you are using arbitrary number of dimensions, you must have a way of addressing elements (I would be curious how you are implementing this). Your implementation of this will affect how you set the destination index. But an obvious way would be with if statements checked in the iteration loops.

很酷不放纵 2024-07-11 11:05:49

你在 c/c++ 中这样做......所以你有一个数组的数组的数组......你不必可视化 20 维,因为这不是数据在内存中的布局方式,对于 2 Dimension:

[1] --> [1,2,3,4,5,6,...]
[2] --> [1,2,3,4,5,6,...]
[3] --> [1,2,3,4,5,6,...]
[4] --> [1,2,3,4,5,6,...]
[5] --> [1,2,3,4,5,6,...]
 .           .
 .           .
 .           .

那么,为什么你不能迭代第一个来总结它的内容呢? 如果您试图找到大小,那么 sizeof(array)/sizeof(int) 是一种有风险的方法。 您必须知道能够处理此数据的维度,并设置内存,以便您知道求和的递归深度。 这是一些你应该做的伪代码,

sum( n_matrix, depth )
  running_total = 0
  if depth = 0 then
    foreach element in the array
      running_total += elm
  else 
     foreach element in the array
       running_total += sum( elm , depth-1 )
  return running_total

You're doing this in c/c++... so you have an array of array of array... you don't have to visualize 20 dimensions since that isn't how the data is laid out in memory, for a 2 dimensional:

[1] --> [1,2,3,4,5,6,...]
[2] --> [1,2,3,4,5,6,...]
[3] --> [1,2,3,4,5,6,...]
[4] --> [1,2,3,4,5,6,...]
[5] --> [1,2,3,4,5,6,...]
 .           .
 .           .
 .           .

so, why can't you iterate across the first one summing it's contents? If you are trying to find the size, then sizeof(array)/sizeof(int) is a risky approach. You must know the dimension to be able to process this data, and set the memory up, so you know the depth of recursion to sum. Here is some pseudo code of what it seems you should do,

sum( n_matrix, depth )
  running_total = 0
  if depth = 0 then
    foreach element in the array
      running_total += elm
  else 
     foreach element in the array
       running_total += sum( elm , depth-1 )
  return running_total
孤城病女 2024-07-11 11:05:49
x = number_of_dimensions;
while (x > 1)
{
  switch (x)
  {
    case 20:
      reduce20DimensionArray();
      x--;
    break;
    case 19:
      .....
  }
}

(抱歉,没能抗拒。)

x = number_of_dimensions;
while (x > 1)
{
  switch (x)
  {
    case 20:
      reduce20DimensionArray();
      x--;
    break;
    case 19:
      .....
  }
}

(Sorry, couldn't resist.)

南巷近海 2024-07-11 11:05:49

如果您使用STL容器,或者Boost.MultiArray,这种事情会容易得多。 但如果你必须使用数组:

#include <iostream>
#include <boost/foreach.hpp>
#include <vector>

int sum(int x) {
    return x;
}

template <class T, unsigned N>
int sum(const T (&x)[N]) {
    int r = 0;
    for(int i = 0; i < N; ++i) {
        r += sum(x[i]);
    }
    return r;
}

template <class T, unsigned N>
std::vector<int> reduce(const T (&x)[N]) {
    std::vector<int> result;
    for(int i = 0; i < N; ++i) {
        result.push_back(sum(x[i]));
    }
    return result;
}

int main() {
    int x[][2][2] = {
        { { 1, 2 }, { 3, 4 } },
        { { 5, 6 }, { 7, 8 } }
    };

    BOOST_FOREACH(int v, reduce(x)) {
        std::cout<<v<<"\n";
    }
}

This kind of thing is much easier if you use STL containers, or maybe Boost.MultiArray. But if you must use an array:

#include <iostream>
#include <boost/foreach.hpp>
#include <vector>

int sum(int x) {
    return x;
}

template <class T, unsigned N>
int sum(const T (&x)[N]) {
    int r = 0;
    for(int i = 0; i < N; ++i) {
        r += sum(x[i]);
    }
    return r;
}

template <class T, unsigned N>
std::vector<int> reduce(const T (&x)[N]) {
    std::vector<int> result;
    for(int i = 0; i < N; ++i) {
        result.push_back(sum(x[i]));
    }
    return result;
}

int main() {
    int x[][2][2] = {
        { { 1, 2 }, { 3, 4 } },
        { { 5, 6 }, { 7, 8 } }
    };

    BOOST_FOREACH(int v, reduce(x)) {
        std::cout<<v<<"\n";
    }
}
贪恋 2024-07-11 11:05:49

当您说您不知道有多少个维度时,您到底是如何定义数据结构的?

在某些时候,有人需要创建这个数组,为此,他们需要知道数组的维度。 您可以强制创建者将此数据与数组一起传递。

除非问题是定义这样的数据结构......

When you say you don't know how many dimensions there are, how exactly are you defining the data structures?

At some point, someone needs to create this array, and to do that, they need to know the dimensions of the array. You can force the creator to pass in this data along with the array.

Unless the question is to define such a data structure...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文