Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 有可能优化代码吗?_.net_Vb.net_Algorithm - Fatal编程技术网

.net 有可能优化代码吗?

.net 有可能优化代码吗?,.net,vb.net,algorithm,.net,Vb.net,Algorithm,我对速度感兴趣,而不是好看的代码,这就是为什么我使用数组而不是整数列表 我有一个数组,看起来像:0,1,0,1,1,0,1,0,1,1,1,0,0,1 我对每个数字的位置很感兴趣,所以我以后可以随机选择一个 所以我要做的是在数组中循环取每个1的位置号,然后创建一个新数组,如下所示:2,4,5,7,9,10,11,14 这里是否可以使用按位?我不知道 代码如下所示: Private Function theThing() As Integer() Dim x As Integer

我对速度感兴趣,而不是好看的代码,这就是为什么我使用数组而不是整数列表

我有一个数组,看起来像:0,1,0,1,1,0,1,0,1,1,1,0,0,1

我对每个数字的位置很感兴趣,所以我以后可以随机选择一个

所以我要做的是在数组中循环取每个1的位置号,然后创建一个新数组,如下所示:2,4,5,7,9,10,11,14

这里是否可以使用按位?我不知道

代码如下所示:

Private Function theThing() As Integer()
    Dim x As Integer
    'arIn() would be a parameter
    Dim arIn() As Integer = {0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}
    Dim ar() As Integer = Nothing
    Dim arCount As Integer = -1

    For x = 1 To arIn.GetUpperBound(0)
        If arIn(x) = 1 Then
            arCount += 1
        End If
    Next

    If arCount > -1 Then
        'using redim preseve is slower than the loop above
        ReDim ar(arCount)

        arCount = 0
        For x = 1 To arIn.GetUpperBound(0)
            If arIn(x) = 1 Then
                ar(arCount) = x
                arCount += 1
            End If
        Next
    End If

    Return ar
End Function
*编辑*

目前的解决方案比现在快10%到15%

Private Function theThing() As Integer
    Dim ar() As Integer = {0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}
    Dim arLenght As Integer = ar.GetUpperBound(0)
    Dim arCount As Integer = 0
    Dim x As Integer

    For x = 1 To arLenght
        If ar(x) = 1 Then
            ar(arCount) = x
            arCount += 1
        End If
    Next

    dim r As New Random()

    Return ar(r.Next(arCount))
End Function
我不认为它可以被优化得更多,除非有人找到一种方法来做解决方案所做的事情,但要快得多

在回答这个问题之前,我的整个过程是每10秒跑25500次


现在,它可以做超过32250的所有时间,21%的增长,谢谢

多少物品的速度

更换物品

编译时间还是执行时间

有什么空间限制

一个已知的策略是将几个组合在一起,写出所有组合及其结果: 0000 -> 0001 -> 4 0010 -> 3 0011 -> 3,4 0100 -> 2 0101 -> 2,4 0110 -> 2,3


为什么要从这个二进制表示转换为随机的一位?这不太可能有助于提高绩效。最好将它们按8位分组,使用一个表格告诉您组中有多少个1,然后重复5次。那你就知道有多少了。对该项进行随机搜索,然后查找所选项。

速度为多少项

更换物品

编译时间还是执行时间

有什么空间限制

一个已知的策略是将几个组合在一起,写出所有组合及其结果: 0000 -> 0001 -> 4 0010 -> 3 0011 -> 3,4 0100 -> 2 0101 -> 2,4 0110 -> 2,3


为什么要从这个二进制表示转换为随机的一位?这不太可能有助于提高绩效。最好将它们按8位分组,使用一个表格告诉您组中有多少个1,然后重复5次。那你就知道有多少了。对其进行随机搜索,然后查找所选的整数。

与其存储整数数组,为什么不将它们全部放入一个整数中

oldArray = [0, 1, 1, 0, 1]
newValue =  22     (binary 10110)
如果要检查是否设置了特定的位位置,请将该位置的幂与2进行位比较:

is position 2 set?
value:    10110
4 (2^2):  00100
result:   00100 --> true

is position 0 set?
value:    10110
1 (2^0):  00001
result:   00000 --> false
搜索按位比较,您会发现很多帮助

以下是一些很好的堆栈溢出问题,可能会有所帮助:

与其存储整数数组,为什么不将它们全部放入一个整数中

oldArray = [0, 1, 1, 0, 1]
newValue =  22     (binary 10110)
如果要检查是否设置了特定的位位置,请将该位置的幂与2进行位比较:

is position 2 set?
value:    10110
4 (2^2):  00100
result:   00100 --> true

is position 0 set?
value:    10110
1 (2^0):  00001
result:   00000 --> false
搜索按位比较,您会发现很多帮助

以下是一些很好的堆栈溢出问题,可能会有所帮助:

您可能会发现,使用For Each和至少初始化为输入数组长度的列表比索引器更快:

If arIn.Length > 0 Then
  Dim lstOut As New List(Of Integer)(arIn.Length)
  Dim ix As Integer = 0
  For Each val As Integer In arIn
    If val = 1 Then
      lstOut.Add(ix)
    End If
    ix = ix + 1
  End If
  Return lstOut.ToArray()
Else
  Return Nothing
End If

但您必须对其进行测试。

您可能会发现,使用For Each和一个至少初始化为输入数组长度的列表比使用索引器更快:

If arIn.Length > 0 Then
  Dim lstOut As New List(Of Integer)(arIn.Length)
  Dim ix As Integer = 0
  For Each val As Integer In arIn
    If val = 1 Then
      lstOut.Add(ix)
    End If
    ix = ix + 1
  End If
  Return lstOut.ToArray()
Else
  Return Nothing
End If

但是你必须对它进行测试。

这就是它的用途。

这就是它的用途。

关于原始算法的一些提示:

尝试将arIn.GetUpperBound0的结果存储在变量中。我不知道VB是如何生成循环的,但每次迭代都有可能调用该函数一次。不过你应该检查一下。 如果arCount>-1总是为真。移除它。 如果您希望保持相同的输入/输出,那么我认为没有什么可以改进的

现在,如果你想要一个函数也可以进行随机选择,那么它可能会更好一些。我会用C写,因为我更了解它。您应该能够理解:

public static int GetRandomSetBit(int[] AllBits)
{
    // Perhaps check here if AllBits is null/empty. I'll skip that for now.

    int L = AllBits.Length;
    int SetBitCount = 0;

    // No point to save a few bytes here. Also - you can make a global array
    // large enough for all occasions and skip allocating it every time.
    // In that case consider automatic resizing and watch out for
    // multithreading issues (if you use several threads).
    int[] GoodPositions = new int[L];

    for ( int i = 0; i < L; i++ )
        if ( AllBits[i] != 0 )
        {
            GoodPositions[SetBitCount] = i;
            SetBitCount++;
        }
     Random r = new Random(); // Should use one global instance
     return GoodPositions[r.Next(SetBitCount)];
}

恐怕再好不过了。除非您能够以某种方式更改输入/输出或要求。

关于原始算法的一些提示:

尝试将arIn.GetUpperBound0的结果存储在变量中。我不知道VB是如何生成循环的,但每次迭代都有可能调用该函数一次。不过你应该检查一下。 如果arCount>-1总是为真。移除它。 如果您希望保持相同的输入/输出,那么我认为没有什么可以改进的

现在,如果你想要一个函数也可以进行随机选择,那么它可能会更好一些。我会用C写,因为我更了解它。您应该能够理解:

public static int GetRandomSetBit(int[] AllBits)
{
    // Perhaps check here if AllBits is null/empty. I'll skip that for now.

    int L = AllBits.Length;
    int SetBitCount = 0;

    // No point to save a few bytes here. Also - you can make a global array
    // large enough for all occasions and skip allocating it every time.
    // In that case consider automatic resizing and watch out for
    // multithreading issues (if you use several threads).
    int[] GoodPositions = new int[L];

    for ( int i = 0; i < L; i++ )
        if ( AllBits[i] != 0 )
        {
            GoodPositions[SetBitCount] = i;
            SetBitCount++;
        }
     Random r = new Random(); // Should use one global instance
     return GoodPositions[r.Next(SetBitCount)];
}

恐怕再好不过了。除非您能够以某种方式更改输入/输出或要求。

我发现很难相信,除非它本身在循环中,否则redim preserve会比您的循环慢

在这种情况下,对于原始速度,不要仅仅为了设置ar的大小而计算arIn中1的数量。因为ar永远不会很大 ger而不是arIn,只需将其设置为相同的大小,最后的redim preserve不会变慢,因为它位于循环之外,并且将始终进行修剪,而不是扩展-希望VB可以在适当的位置执行此操作,而不是分配更多内存。此外,如果VB每次通过循环计算arIn的缓存大小(如果允许ReDim),则很可能会计算arIn的缓存大小

Private Function theThing() As Integer()
    Dim x As Integer
    'arIn() would be a parameter
    Dim arIn() As Integer = {0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}
    Dim ar(arIn.GetUpperBound(0)) As Integer
    Dim arCount As Integer
    Dim arInCount As Integer

    arCount = 0
    arInCount = arIn.GetUpperBound(0)
    For x = 1 To arInCount
        If arIn(x) = 1 Then
            ar(arCount) = x
            arCount += 1
        End If
    Next

    ReDim Preserve ar(arCount)
    Return ar
End Function
或者,如果稍微调整返回的内容,可以完全删除redim。使返回数组比输入数组大一个,并使用第一个元素控制要随机选择的数组部分

对于您的示例,返回的数组将是:

{8,2,4,5,7,9,10,11,14,?,?,?,?,?,?} (? values are irrelevant).
 ^ <-------+--------> <----+---->
 |         |               |
 |         |               +-- These are unused.
 |         |
 |         +-- These are used.
 |
 +-- This is the count of elements to use.
Private Function theThing() As Integer()
    Dim x As Integer
    'arIn() would be a parameter
    Dim arIn() As Integer = {0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}
    Dim ar(arIn.GetUpperBound(0)+1) As Integer
    Dim arCount As Integer
    Dim arInCount As Integer

    arCount = 0
    arInCount = arIn.GetUpperBound(0)
    For x = 1 To arInCount
        If arIn(x) = 1 Then
            ar(arCount) = x
            arCount += 1
        End If
    Next

    ar(0) = arCount
    Return ar
End Function
然后,在从ar中选择随机值的代码中,而不是:

rndval = rnd(ar.GetUpperBound)
使用:


我发现很难相信redim preserve会比您的循环慢,除非它本身在循环中

在这种情况下,对于原始速度,不要仅仅为了设置ar的大小而计算arIn中的1的数量。因为ar永远不会比arIn大,所以只需将其设置为相同的大小,最后的redim PREVENT不会变慢,因为它在循环之外,并且将始终处于修剪状态,不扩展-希望VB可以就地完成,而不是分配更多内存。此外,如果VB每次通过循环计算arIn的缓存大小(如果允许ReDim),则很可能会计算arIn的缓存大小

Private Function theThing() As Integer()
    Dim x As Integer
    'arIn() would be a parameter
    Dim arIn() As Integer = {0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}
    Dim ar(arIn.GetUpperBound(0)) As Integer
    Dim arCount As Integer
    Dim arInCount As Integer

    arCount = 0
    arInCount = arIn.GetUpperBound(0)
    For x = 1 To arInCount
        If arIn(x) = 1 Then
            ar(arCount) = x
            arCount += 1
        End If
    Next

    ReDim Preserve ar(arCount)
    Return ar
End Function
或者,如果稍微调整返回的内容,可以完全删除redim。使返回数组比输入数组大一个,并使用第一个元素控制要随机选择的数组部分

对于您的示例,返回的数组将是:

{8,2,4,5,7,9,10,11,14,?,?,?,?,?,?} (? values are irrelevant).
 ^ <-------+--------> <----+---->
 |         |               |
 |         |               +-- These are unused.
 |         |
 |         +-- These are used.
 |
 +-- This is the count of elements to use.
Private Function theThing() As Integer()
    Dim x As Integer
    'arIn() would be a parameter
    Dim arIn() As Integer = {0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}
    Dim ar(arIn.GetUpperBound(0)+1) As Integer
    Dim arCount As Integer
    Dim arInCount As Integer

    arCount = 0
    arInCount = arIn.GetUpperBound(0)
    For x = 1 To arInCount
        If arIn(x) = 1 Then
            ar(arCount) = x
            arCount += 1
        End If
    Next

    ar(0) = arCount
    Return ar
End Function
然后,在从ar中选择随机值的代码中,而不是:

rndval = rnd(ar.GetUpperBound)
使用:


也许您可以通过使用转换表来压缩最大性能。然后应用以下算法:

很抱歉,我不再精通VB,所以我必须编写C。这里是整个代码的一部分,因为整个lookupTable将有256项

using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        var input = new byte[] { 0x5A /*01011010b*/, 0xE4 /*11100100b*/ };
        var output = new List<int>();
        var lookupTable = new int[][] { new int[0] /*00000000b*/
                                           , new int[] { 8 }    /*00000001b*/
                                           , new int[] { 7 }    /*00000010b*/
                                           , new int[] { 7,8 }  /*00000011b*/
                                           , new int[] { 6 }    /*00000100b*/
                                           , new int[] { 6,8 }  /*00000101b*/
                                           , new int[] { 6,7,8 }  /*00000111b*/
                                          };
        int offset = 0;
        foreach (var value in input)
        {
            foreach (var position in lookupTable[(int)value])
            {
                output.Add(position + offset);
            }
            offset += 8;
        }
    }
}

也许您可以通过使用转换表来压缩最大性能。然后应用以下算法:

很抱歉,我不再精通VB,所以我必须编写C。这里是整个代码的一部分,因为整个lookupTable将有256项

using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        var input = new byte[] { 0x5A /*01011010b*/, 0xE4 /*11100100b*/ };
        var output = new List<int>();
        var lookupTable = new int[][] { new int[0] /*00000000b*/
                                           , new int[] { 8 }    /*00000001b*/
                                           , new int[] { 7 }    /*00000010b*/
                                           , new int[] { 7,8 }  /*00000011b*/
                                           , new int[] { 6 }    /*00000100b*/
                                           , new int[] { 6,8 }  /*00000101b*/
                                           , new int[] { 6,7,8 }  /*00000111b*/
                                          };
        int offset = 0;
        foreach (var value in input)
        {
            foreach (var position in lookupTable[(int)value])
            {
                output.Add(position + offset);
            }
            offset += 8;
        }
    }
}
禁用溢出检查。 项目属性->编译->高级编译选项->删除整数溢出检查。 如果需要对项目的其余部分进行溢出检查,则可以将代码移动到新项目(例如DLL),并禁用该新项目的溢出检查

还要确保您正在运行一个启用了buildoptimizations的版本,并且没有调试它

编辑:如果我在For中声明用于测试调用函数5000万次的数组,我会得到8.5s 12秒。如果你只得到32000,要么你使用了非常大的输入,要么你的代码速度变慢了。例如,如果您正在计算程序内部的时间,并且在探查器中运行它,您将得到错误的结果,因为探查可能会显著降低程序的速度。这样的小故障也会影响性能

禁用溢出检查。 项目属性->编译->高级编译选项->删除整数溢出检查。 如果需要对项目的其余部分进行溢出检查,则可以将代码移动到新项目(例如DLL),并禁用该新项目的溢出检查

还要确保您正在运行一个启用了buildoptimizations的版本,并且没有调试它


编辑:如果我在For中声明用于测试调用函数5000万次的数组,我会得到8.5s 12秒。如果你只得到32000,要么你使用了非常大的输入,要么你的代码速度变慢了。例如,如果您正在计算程序内部的时间,并且在探查器中运行它,您将得到错误的结果,因为探查可能会显著降低程序的速度。这样的小故障也会影响性能

如果根据数组的大小很容易生成一个略大于数组长度的素数,这可能很容易,也可能不容易,而且您不关心完全一致随机,那么您可以在该范围内生成一个随机数并生成该循环。它应该在几次迭代中根据1的密度找到答案。c语言源代码,因为我不记得vb语法:

int RandomInArray(int[] ar)
{
    int p = GenerateSlightlyLargerPrime(ar.Length);

    int x = random.nextInt(p);
    int i = x;
    do
    {
       if (i < ar.Length && ar[i] == 1)
           return i;
       i = (i + x) % p;
    } while (i != x);
    return -1;
}

请注意,这不是100%一致随机的,但它应该相当接近。

如果根据数组的大小很容易生成一个略大于数组长度的素数,这可能很容易,也可能不容易,而且您不关心完全一致随机,然后你可以在这个范围内生成一个随机数,并生成这个循环。它应该在几次迭代中根据1的密度找到答案。c语言源代码,因为我不记得vb语法:

int RandomInArray(int[] ar)
{
    int p = GenerateSlightlyLargerPrime(ar.Length);

    int x = random.nextInt(p);
    int i = x;
    do
    {
       if (i < ar.Length && ar[i] == 1)
           return i;
       i = (i + x) % p;
    } while (i != x);
    return -1;
}
请注意,这不是100%一致随机的,但它应该相当接近。

我认为当 e引用了BitArray,他的意思是:

using System.Collections.Generic;
using System;
using System.Collections;

class Program
{
    static void Main(string[] args)
    {
        var input = new BitArray(new byte[] { 0x5A /*01011010b*/
                                        , 0xE4 /*11100100b*/ });
        var output = new List<int>();
        var offset = 1;
        foreach (var bit in input)
        {
            if (bit)
            {
                output.Add(offset);
            }
            offset++;
        }
    }
}

我认为当递归引用BitArray时,他的意思是这样的:

using System.Collections.Generic;
using System;
using System.Collections;

class Program
{
    static void Main(string[] args)
    {
        var input = new BitArray(new byte[] { 0x5A /*01011010b*/
                                        , 0xE4 /*11100100b*/ });
        var output = new List<int>();
        var offset = 1;
        foreach (var bit in input)
        {
            if (bit)
            {
                output.Add(offset);
            }
            offset++;
        }
    }
}

我尝试了不同的方法。这样做的目的是在找到与1对应的条目时,继续获得一个随机入口和出口。此解决方案并不完美,因为未使用某些随机数,这些随机数可能会破坏随机性,也可能不会破坏随机性。此外,速度在很大程度上取决于1s的密度。代码如下:

public static int GetRandomSetBit(int[] AllBits)
{
    int L = AllBits.Length;
    Random r = new Random();    // Better use a global instance as this hurt performance a lot
    do
    {
         selected = r.Next(L);

    } while (AllBits[selected] == 0);
    return selected;
}
在我的电脑中,如果将随机对象的创建移动到全局,如果30个1中有5个1,它可以在大约11秒内运行50000000次试验。如果最多有15个1s,则所需时间将缩短到5s左右


与Vilx建议的代码相比,他的代码在13秒左右可以在我的电脑上运行50000000次试用。这样做的目的是在找到与1对应的条目时,继续获得一个随机入口和出口。此解决方案并不完美,因为未使用某些随机数,这些随机数可能会破坏随机性,也可能不会破坏随机性。此外,速度在很大程度上取决于1s的密度。代码如下:

public static int GetRandomSetBit(int[] AllBits)
{
    int L = AllBits.Length;
    Random r = new Random();    // Better use a global instance as this hurt performance a lot
    do
    {
         selected = r.Next(L);

    } while (AllBits[selected] == 0);
    return selected;
}
在我的电脑中,如果将随机对象的创建移动到全局,如果30个1中有5个1,它可以在大约11秒内运行50000000次试验。如果最多有15个1s,则所需时间将缩短到5s左右



与Vilx建议的代码相比,他的代码可以在我的PC上运行50000000次测试,大约13秒

数组中的项?在0到36-40之间,您所说的更改项是什么意思?执行时间,因为它可以在一个巨大的循环中使用,没有实际的空间限制。如我所说,我对数组中的position.item感兴趣?在0到36-40之间,你所说的更改项目是什么意思?执行时间,因为它可以在一个巨大的循环中使用,没有实际的空间限制。如我所说,我对位置感兴趣。我想存储每个真实位的位置,以便我可以在列表中随机选择一个,我对位置感兴趣。如果数组索引超过32个,则中断。您的位位置偏离一个位置。8=1000bin,16=10000bin又名2^3 2^2^1 2^0+1-问题描述要求实现位向量。Pax注意,有一些方法可以实现任意大小。我想存储每个真实位的位置,这样我可以在列表中随机选择一个,我对位置感兴趣。如果数组索引超过32个,则中断。您的位位置将偏离一个位置。8=1000bin,16=10000bin又名2^3 2^2^1 2^0+1-问题描述要求实现位向量。请Pax注意,有一些方法可以实现任意大小的数组。@Mitch Wheat,在10秒内,我比在循环上面使用我的代码要多,对于T的列表,我运行26295个数组,运行25390个。好的,你可以删除这个单词,但它仍然是slower@Mitch小麦,在10秒内,我比在循环上面使用我的代码做得更多,对于T的列表,我运行26295个数组,运行25390个。好的,你可以删除这个单词,但它仍然很慢。有趣的是,我会研究它。如果我现在的工作做得很快,我可能不得不对它进行一次大的重新编码。我看不到一个简单的方法来做我想做的事情,存储真实值的位置,这样我就可以在那个列表上进行随机编码。有趣的是,我会研究它。我可能不得不对我当前的工作进行一次大的重新编码,如果它运行得更快的话。我看不到一个简单的方法来做我想做的事情,存储真实值的位置,这样我就可以在列表上随机做+1来存储getupperbound0,从25500-26500到,对于我的5次测试,27000-27400次运行,10秒以上循环,有时会出现不真实的比特,这就是为什么我要检查arcount>-1,修复了上面的代码,使其成为-1个错误的选择。现在你打翻了柜台,它将在1点前关闭。您应该在开始时将其单独设置为0,而不是-1,然后删除IF。然后它会很好地工作。我希望我能给你另一个+1的想法,在SetbitCount上做随机现在做超过28000,如果在接下来的30分钟内没有更好的方法,我可能会把你标记为答案。当然你不能,因为访问每个值需要几个位操作。现在它只是一个数组查找。+1用于存储getupperbound0,从25500-26500到,对于我的5个测试,超过27000-27400次运行,循环时间超过10秒。有时会出现不正确的位,这就是为什么我检查arcount>-1修复了上面的代码,使其成为-1个错误的选择。现在你打翻了柜台,它将在1点前关闭。您应该在开始时将其单独设置为0,而不是-1,然后删除IF。然后它会很好地工作。我希望我能给你另一个+1的想法,在SetbitCount上做随机现在做超过28000,如果在接下来的30分钟内没有更好的方法,我可能会把你标记为答案。当然你不能,因为访问每个值需要几个位操作。现在它只是一个数组查找。是的,你是对的,Vilx让我意识到,早些时候我用preserve进行测试时,它在循环中,这比我的第一个解决方案更糟糕

on可能更好,尤其是如果您希望最小化对调用代码的更改。我的问题的结果可以在这里找到,谢谢!是的,你是对的,Vilx-让我意识到,早些时候,当我使用preserve进行测试时,它在循环中,这是非常糟糕的,那么我的第一个解决方案可能更好,特别是如果你希望最小化对调用代码的更改。我的问题的结果可以在这里找到,谢谢!请注意我在代码中暗示的另外两个优化—将r和ar提升为全局变量。在不可避免的r之后,这些分配可能是目前过程中最慢的事情。当然,下一步。r实际上已经在类级别,对于上面的代码,我将其移动到函数内部,对于ar,我不确定将其移动到类级别是否会有帮助,因为长度总是会改变,现在返回数组的一个元素,这意味着每次需要值时都必须执行此函数,是吗?我觉得这一点效率都不高。最好返回数组并选择此函数之外的元素,我认为。@Pax我对数组所做的只是检查它是否为空,然后进行随机,我在函数外删除了一个if,这是很好的。如果你必须从同一个列表中选择几个项目,那么缓存ar肯定比每次都重新计算要好。请注意我在代码中暗示的另外两个优化—将r和ar提升为全局变量。在不可避免的r之后,这些分配可能是目前过程中最慢的事情。当然,下一步。r实际上已经在类级别,对于上面的代码,我将其移动到函数内部,对于ar,我不确定将其移动到类级别是否会有帮助,因为长度总是会改变,现在返回数组的一个元素,这意味着每次需要值时都必须执行此函数,是吗?我觉得这一点效率都不高。最好返回数组并选择此函数之外的元素,我认为。@Pax我对数组所做的只是检查它是否为空,然后进行随机,如果你必须从同一个列表中选取几个项目,那么最好是缓存ar,而不是每次都重新计算它。有时,它可能都是假值是的,正如我所说,这不是一个完美的解决方案。如果输入全部为零,它将永远不会返回。事实上,如果1s太少,这个算法的性能会很差。有时,它可能都是假值是的,正如我说的,它不是一个完美的解决方案。如果输入全部为零,它将永远不会返回。实际上,如果1s太少,这个算法的性能会很差。我的问题的结果可以在这里找到,谢谢!我的问题结果可以在这里找到,谢谢!