C# 高效的.NET对处理

C# 高效的.NET对处理,c#,arrays,list,collections,generics,C#,Arrays,List,Collections,Generics,以下代码允许您处理所有可能的对象对(其中DoSomething(a,b)等同于DoSomething(b,a),您不想同时执行这两个操作,并且您永远不需要DoSomething(a,a)): void MyMethod(虚构[]myArray) { 对于(int j=0;j

以下代码允许您处理所有可能的对象对(其中DoSomething(a,b)等同于DoSomething(b,a),您不想同时执行这两个操作,并且您永远不需要DoSomething(a,a)):

void MyMethod(虚构[]myArray)
{
对于(int j=0;j<(myArray.Length-1);+j)
{
对于(int k=j+1;k
我知道这大约是n*n/2次操作

如果使用
列表而不是数组,是否有同样有效的方法来处理所有可能的对?(特别是一个解决方案,我不必在内部循环中旋转已经完成的元素)。也许是使用了枚举器

数组不好,因为我事先不知道需要多少神话(可能是0,可能永远不会超过1000)。对于这种特殊用途,是否有比
列表
更好的集合?我不需要排序,我只创建新集合、清除现有集合、添加到集合、枚举集合或如上所述处理配对。无论我使用什么收藏,我都可能需要100到10000个,所以创建/保存它们的成本不会太高


假设DoSomething()正在对移动对象执行碰撞检测和响应。

在这种情况下,总是有机会记忆算法,但如果不了解有关DoSomething的更多详细信息,则无法说出可以做什么

例如,假设
DoSomething
如下所示:

void DoSomething(MyThing arg1, MyThing arg2)
{
    // Let's assume MyThing.Value is an int
    // and you want to print the product of both values
    Console.WriteLine(arg1.Value * arg2.Value);
}

在本例中,我们可以跟踪在内存中传递了哪些参数,并且只为我们尚未看到的参数组合调用该方法。当然,这只适用于需要大量执行时间来保证记忆开销的
DoSomething
实现。

在这种情况下,总是有机会记忆算法,但如果不了解
DoSomething
的更多细节,就不可能说出可能发生的情况完成了

例如,假设
DoSomething
如下所示:

void DoSomething(MyThing arg1, MyThing arg2)
{
    // Let's assume MyThing.Value is an int
    // and you want to print the product of both values
    Console.WriteLine(arg1.Value * arg2.Value);
}
在本例中,我们可以跟踪在内存中传递了哪些参数,并且只为我们尚未看到的参数组合调用该方法。当然,这仅适用于需要大量执行时间来保证内存开销的
DoSomething
实现。

列表
将正常工作。您只需将方法签名中的
MyThing[]
替换为
List

如果您正在寻找一种可用于枚举的解决方案,那么就为了它:

void MyMethod<T>(IEnumerable<T> myThings, Action<T, T> action)
{
    int index = 0;
    foreach (var a in myThings)
        foreach (var b in myThings.Skip(++index))
            action(a, b);
}
void MyMethod(IEnumerable myThings,Action-Action)
{
int指数=0;
foreach(神话中的var a)
foreach(myThings.Skip(++索引)中的变量b)
行动(a、b);
}
请注意,这会稍微慢一点,因为
Skip
实际上会迭代跳过的元素。这可能会抵消您在接近列表末尾时从内存缓存中获得的任何好处,当然这会浪费时间丢弃前N个元素。

list
可以正常工作。您只需将方法签名中的
MyThing[]
替换为
List

如果您正在寻找一种可用于枚举的解决方案,那么就为了它:

void MyMethod<T>(IEnumerable<T> myThings, Action<T, T> action)
{
    int index = 0;
    foreach (var a in myThings)
        foreach (var b in myThings.Skip(++index))
            action(a, b);
}
void MyMethod(IEnumerable myThings,Action-Action)
{
int指数=0;
foreach(神话中的var a)
foreach(myThings.Skip(++索引)中的变量b)
行动(a、b);
}

请注意,这会稍微慢一点,因为
Skip
实际上会迭代跳过的元素。当您接近列表末尾时,这可能会抵消您从内存缓存中获得的任何好处,当然,丢弃前N个元素会浪费时间。

N个项目的唯一组合的数量是N/(2!(N-2)!=N(N-1)/2~=O(N^2)。要对列表中两个项目的每一个组合执行一个操作,其复杂性是无法降低的

就要使用的集合而言,一个列表将直接插入到您拥有数组的位置,只需进行一次更改;列表使用Count属性来确定基数,而不是长度

至于更优雅的As和Bs组合方式,Linq确实有一些优势:

var combinations = 
    from a in myThings.Reverse()
    from b in myThings.TakeWhile(x=>x!=a)
    select new {a,b};

foreach(var combo in combinations)
   DoSomething(combo.a, combo.b);

这仍然会比您原来的算法慢,但我认为它会比cdhowie的算法快一点,因为它将只遍历N个额外的项(以创建Reverse()枚举),而不是跳过N(N-1)正如cdhowie的内部foreach最终所做的那样。

每次取2个的N个项目的唯一组合的数量是N/(2!(N-2)!=N(N-1)/2~=O(N^2)。要对列表中两个项目的每一个组合执行一个操作,其复杂性是无法降低的

就要使用的集合而言,一个列表将直接插入到您拥有数组的位置,只需进行一次更改;列表使用Count属性来确定基数,而不是长度

至于更优雅的As和Bs组合方式,Linq确实有一些优势:

var combinations = 
    from a in myThings.Reverse()
    from b in myThings.TakeWhile(x=>x!=a)
    select new {a,b};

foreach(var combo in combinations)
   DoSomething(combo.a, combo.b);
这仍然会比您原来的算法慢,但我认为它会比cdhowie的算法快一点,因为它将只遍历N个额外的项(以创建Reverse()枚举),而不是像cdhowie的内部foreach那样跳过N(N-1)

有没有同样有效的方法 处理所有可能的对,如果 使用列表而不是 阵列

List
只是一个围绕
T[]
的花式包装,当超出列表容量时,它会偶尔调整大小

你的算法已经是最优的了。如果要将其与
列表一起使用,只需更改declar即可