Como preencher / instanciar uma matriz C # com um único valor?

205

Eu sei que matrizes instanciadas de tipos de valor em C # são preenchidas automaticamente com o valor padrão do tipo (por exemplo, false para bool, 0 para int, etc.).

Existe uma maneira de preencher automaticamente uma matriz com um valor inicial que não é o padrão? Na criação ou em um método interno posteriormente (como Arrays.fill () do Java )? Digamos que eu quisesse uma matriz booleana que fosse verdadeira por padrão, em vez de falsa. Existe uma maneira interna de fazer isso ou você apenas precisa percorrer a matriz com um loop for?

 // Example pseudo-code:
 bool[] abValues = new[1000000];
 Array.Populate(abValues, true);

 // Currently how I'm handling this:
 bool[] abValues = new[1000000];
 for (int i = 0; i < 1000000; i++)
 {
     abValues[i] = true;
 }

Ter que percorrer a matriz e "redefinir" cada valor para true parece ineficaz. Existe alguma maneira de contornar isso? Talvez lançando todos os valores?

Depois de digitar essa questão e pensar sobre isso, acho que os valores padrão são simplesmente o resultado de como o C # lida com a alocação de memória desses objetos nos bastidores, então imagino que provavelmente não seja possível fazer isso. Mas eu ainda gostaria de ter certeza!

patjbs
fonte
Normalmente, mudo o nome de is_found para is_still_hiding. Adoro as respostas, porém, eu precisava fazer semelhante para a matriz de int em um caso de teste. (boa pergunta)
ctrl-alt-delor 16/11/11

Respostas:

146

Não conhece um método de estrutura, mas você pode escrever um auxiliar rápido para fazer isso por você.

public static void Populate<T>(this T[] arr, T value ) {
  for ( int i = 0; i < arr.Length;i++ ) {
    arr[i] = value;
  }
}
JaredPar
fonte
3
Prefira ++ i em vez de i ++ se você não precisar da cópia.
precisa saber é o seguinte
24
i ++ copia i, incrementa i e retorna o valor original. ++ i apenas retorna o valor incrementado. Portanto, o ++ i é mais rápido, o que pode ser significativo em grandes loops, como estamos falando aqui.
tenpn
57
@RobertDailey: Essa é uma otimização do compilador e não é mais verdadeira. Acabei de testar para verificar minha crença: se o valor de retorno do i ++ não for usado para nada, o compilador o compilará como ++ i automaticamente para você. Além disso, mesmo quando eu uso o valor de retorno, a diferença de desempenho é tão pequena que eu precisava fazer um caso extremo para medi-lo. Mesmo assim, resultou em apenas alguns por cento de tempo de execução diferente.
Edward Ned Harvey ''
8
Eu escrevi um método de extensão como este, mas eu tinha que voltar a matriz original para permitir método de encadeamento, tais como:int[] arr = new int[16].Populate(-1);
Gutblender
2
Mude voidpara T[]e, em seguida, você pode fazervar a = new int[100].Polupate(1)
orad 14/17/17
198
Enumerable.Repeat(true, 1000000).ToArray();
Rony
fonte
70
Enquanto isso funciona, não é realmente uma boa solução, porque é muito lenta; é cerca de 4 vezes mais lento do que iterando com um loop for de fato.
22410 patjbs
4
Sim isso é verdade, quando consideramos o desempenho do loop for é mais rápido
Rony
6
Para ver algum benchmark real, dê uma olhada no C # Initialize Array .
theknut
4
Enumerable.ToArraynão sabe o tamanho da sequência enumerável, por isso precisa adivinhar o tamanho da matriz. Isso significa que você obterá alocações de matriz sempre que ToArrayo buffer for excedido, mais uma alocação no final para o corte. Também há sobrecarga envolvida com o objeto enumerável.
Edward Brey 12/02
5
Apenas uma observação: com os tipos de referência, isso preencherá toda a matriz com todas as referências ao mesmo objeto único. Se não é isso que você deseja e realmente deseja gerar objetos diferentes para cada item da matriz, consulte stackoverflow.com/a/44937053/23715 .
Alex Che
74

Crie uma nova matriz com mil truevalores:

var items = Enumerable.Repeat<bool>(true, 1000).ToArray();  // Or ToList(), etc.

Da mesma forma, você pode gerar sequências inteiras:

var items = Enumerable.Range(0, 1000).ToArray();  // 0..999
bytebender
fonte
8
Não é ruim, mas ainda mais lento do que um loop é de cerca de um fator de 4x
patjbs
1
patjbs em teoria no futuro Enumerable.Repeat terá um desempenho mais rápido porque usará uma implementação paralela.
Petar Petrov
1
@PetarPetrov Isso nunca acontecerá devido à troca de cache. Estou bastante certo de que, devido à natureza do cache da CPU, executar o trabalho em paralelo em uma única matriz sempre será mais lento, não importa o motivo, porque o computador espera um trabalho síncrono e carrega os dados adequadamente.
TernaryTopiary
pessimização pretendida! = falta de otimização prematura.
Denis Gladkiy
24

Para matrizes grandes ou matrizes de tamanho variável, você provavelmente deve usar:

Enumerable.Repeat(true, 1000000).ToArray();

Para matriz pequena, você pode usar a sintaxe de inicialização da coleção em C # 3:

bool[] vals = new bool[]{ false, false, false, false, false, false, false };

O benefício da sintaxe de inicialização da coleção é que você não precisa usar o mesmo valor em cada slot e pode usar expressões ou funções para inicializar um slot. Além disso, acho que você evita o custo de inicializar o slot da matriz para o valor padrão. Então, por exemplo:

bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };
LBushkin
fonte
E para inicializar uma matriz float []:float[] AlzCalDefault = new float[] {(float) 0.5, 18, 500, 1, 0};
Jim Lahman 5/11/12
FWIW inicialização de uma matriz pode ser feito em qualquer versão do C # como:bool[] vals = { false, true, false, !(a || b) && c, SomeBoolMethod() };
Peter van der Heijden
24

Se sua matriz é tão grande, você deve usar o BitArray. Ele usa 1 bit para cada bool, em vez de um byte (como em uma matriz de bools). Você também pode definir todos os bits para true com os operadores de bit. Ou apenas inicialize em true. Se você precisar fazer apenas uma vez, isso custará apenas mais.

System.Collections.BitArray falses = new System.Collections.BitArray(100000, false);
System.Collections.BitArray trues = new System.Collections.BitArray(100000, true);

// Now both contain only true values.
falses.And(trues);
MrFox
fonte
17

Você pode usar Array.Fillno .NET Core 2.0+ e no .NET Standard 2.1+.

juFo
fonte
Excelente! Embora esteja ciente de que é um método relativamente novo. Ele está disponível em .NET Núcleo 2.0+ e .NET padrão 2.1, mas especificamente não em qualquer uma das versões do .NET Framework. (será no .NET 5.0, que combina o .NET Framework e o .NET Core).
Abel
9

infelizmente não acho que exista uma maneira direta, porém acho que você pode escrever um método de extensão para a classe array fazer isso

class Program
{
    static void Main(string[] args)
    {
        int[] arr = new int[1000];
        arr.Init(10);
        Array.ForEach(arr, Console.WriteLine);
    }
}

public static class ArrayExtensions
{
    public static void Init<T>(this T[] array, T defaultVaue)
    {
        if (array == null)
            return;
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = defaultVaue;
        }
    }
}
bashmohandes
fonte
Eu estou gostando da idéia de extensão, quanto mais eu entendo isso. Às vezes, a solução inicial e simples é realmente a melhor!
22410 patjbs #
8

Bem, depois de pesquisar um pouco mais no Google e ler, encontrei o seguinte:

bool[] bPrimes = new bool[1000000];
bPrimes = Array.ConvertAll<bool, bool>(bPrimes, b=> b=true);

O que certamente está mais próximo do que estou procurando. Mas não tenho certeza se isso é melhor do que percorrer a matriz original em um loop for e apenas alterar os valores. Depois de um teste rápido, ele parece mais lento em um fator de 5. Portanto, não é realmente uma boa solução!

patjbs
fonte
4
é semelhante ao que você está tentando fazer, exceto fazer uma chamada de função para cada elemento em sua matriz. Pode parecer muito mais agradável sintaticamente, mas o seu fazendo um trabalho muito mais ...
Nader Shirazie
sim, ele está parecendo um simples loop for faz o trabalho quase tão bem quanto qualquer outra coisa
patjbs
Ele cria uma nova matriz (não altera a instância original).
Jeppe Stig Nielsen
7

Que tal uma implementação paralela

public static void InitializeArray<T>(T[] array, T value)
{
    var cores = Environment.ProcessorCount;

    ArraySegment<T>[] segments = new ArraySegment<T>[cores];

    var step = array.Length / cores;
    for (int i = 0; i < cores; i++)
    {
        segments[i] = new ArraySegment<T>(array, i * step, step);
    }
    var remaining = array.Length % cores;
    if (remaining != 0)
    {
        var lastIndex = segments.Length - 1;
        segments[lastIndex] = new ArraySegment<T>(array, lastIndex * step, array.Length - (lastIndex * step));
    }

    var initializers = new Task[cores];
    for (int i = 0; i < cores; i++)
    {
        var index = i;
        var t = new Task(() =>
        {
            var s = segments[index];
            for (int j = 0; j < s.Count; j++)
            {
                array[j + s.Offset] = value;
            }
        });
        initializers[i] = t;
        t.Start();
    }

    Task.WaitAll(initializers);
}

Ao inicializar apenas uma matriz, o poder desse código não pode ser visto, mas acho que você definitivamente deve esquecer o "puro" para.

Petar Petrov
fonte
Isso arrisca a questão do compartilhamento falso, no qual diferentes threads competem pelas linhas de cache da CPU e, portanto, reduzem o desempenho em comparação com uma implementação de thread único. Se isso acontece depende do tamanho dos blocos de memória por thread e da arquitetura da CPU.
Eric J.
7

O código abaixo combina iteração simples para cópias pequenas e Array.Copy para cópias grandes

    public static void Populate<T>( T[] array, int startIndex, int count, T value ) {
        if ( array == null ) {
            throw new ArgumentNullException( "array" );
        }
        if ( (uint)startIndex >= array.Length ) {
            throw new ArgumentOutOfRangeException( "startIndex", "" );
        }
        if ( count < 0 || ( (uint)( startIndex + count ) > array.Length ) ) {
            throw new ArgumentOutOfRangeException( "count", "" );
        }
        const int Gap = 16;
        int i = startIndex;

        if ( count <= Gap * 2 ) {
            while ( count > 0 ) {
                array[ i ] = value;
                count--;
                i++;
            }
            return;
        }
        int aval = Gap;
        count -= Gap;

        do {
            array[ i ] = value;
            i++;
            --aval;
        } while ( aval > 0 );

        aval = Gap;
        while ( true ) {
            Array.Copy( array, startIndex, array, i, aval );
            i += aval;
            count -= aval;
            aval *= 2;
            if ( count <= aval ) {
                Array.Copy( array, startIndex, array, i, count );
                break;
            }
        }
    }

Os benchmarks para diferentes comprimentos de matriz usando uma matriz int [] são:

         2 Iterate:     1981 Populate:     2845
         4 Iterate:     2678 Populate:     3915
         8 Iterate:     4026 Populate:     6592
        16 Iterate:     6825 Populate:    10269
        32 Iterate:    16766 Populate:    18786
        64 Iterate:    27120 Populate:    35187
       128 Iterate:    49769 Populate:    53133
       256 Iterate:   100099 Populate:    71709
       512 Iterate:   184722 Populate:   107933
      1024 Iterate:   363727 Populate:   126389
      2048 Iterate:   710963 Populate:   220152
      4096 Iterate:  1419732 Populate:   291860
      8192 Iterate:  2854372 Populate:   685834
     16384 Iterate:  5703108 Populate:  1444185
     32768 Iterate: 11396999 Populate:  3210109

As primeiras colunas são o tamanho da matriz, seguido pelo tempo de cópia usando uma iteração simples (implementação @JaredPared). O tempo desse método é depois disso. Estes são os benchmarks usando uma matriz de uma estrutura de quatro números inteiros

         2 Iterate:     2473 Populate:     4589
         4 Iterate:     3966 Populate:     6081
         8 Iterate:     7326 Populate:     9050
        16 Iterate:    14606 Populate:    16114
        32 Iterate:    29170 Populate:    31473
        64 Iterate:    57117 Populate:    52079
       128 Iterate:   112927 Populate:    75503
       256 Iterate:   226767 Populate:   133276
       512 Iterate:   447424 Populate:   165912
      1024 Iterate:   890158 Populate:   367087
      2048 Iterate:  1786918 Populate:   492909
      4096 Iterate:  3570919 Populate:  1623861
      8192 Iterate:  7136554 Populate:  2857678
     16384 Iterate: 14258354 Populate:  6437759
     32768 Iterate: 28351852 Populate: 12843259
Panos Theof
fonte
7

Ou ... você pode simplesmente usar lógica invertida. Vamos falsesignificar truee vice-versa.

Amostra de código

// bool[] isVisible = Enumerable.Repeat(true, 1000000).ToArray();
bool[] isHidden = new bool[1000000]; // Crazy-fast initialization!

// if (isVisible.All(v => v))
if (isHidden.All(v => !v))
{
    // Do stuff!
}
l33t
fonte
solução engraçado, tudo que isso seria muito mais difícil com, por exemplo ints porque você perde a 0.
MrFox
1
esta é realmente uma opção viável se você "inverter a lógica" no nome da variável: em vez de bool[] isVisiblefazer issobool[] isHidden
Markus Hütter
1
As pessoas parecem reagir como se isso fosse algum tipo de truque engraçado. É uma técnica de otimização comum. Se você tiver sorte, o compilador fará isso por você.
L33t
4

isso também funciona ... mas pode ser desnecessário

 bool[] abValues = new bool[1000];
 abValues = abValues.Select( n => n = true ).ToArray<bool>();
Stan R.
fonte
4

Muitas das respostas apresentadas aqui se resumem a um loop que inicializa a matriz um elemento por vez, o que não tira proveito das instruções da CPU projetadas para operar em um bloco de memória de uma só vez.

O .Net Standard 2.1 (em pré-visualização até este momento) fornece Array.Fill () , que se presta a uma implementação de alto desempenho na biblioteca de tempo de execução (embora, a partir de agora, o .NET Core não pareça aproveitar essa possibilidade) .

Para aqueles em plataformas anteriores, o método de extensão a seguir supera um loop trivial por uma margem substancial quando o tamanho da matriz é significativo. Eu o criei quando minha solução para um desafio de código on-line era cerca de 20% acima do orçamento de tempo alocado. Reduziu o tempo de execução em cerca de 70%. Nesse caso, o preenchimento da matriz foi realizado dentro de outro loop. BLOCK_SIZE foi definido pelo instinto em vez de pelo experimento. Algumas otimizações são possíveis (por exemplo, copiar todos os bytes já configurados para o valor desejado em vez de um bloco de tamanho fixo).

internal const int BLOCK_SIZE = 256;
public static void Fill<T>(this T[] array, T value)
{
    if (array.Length < 2 * BLOCK_SIZE)
    {
        for (int i = 0; i < array.Length; i++) array[i] = value;
    }
    else
    {
        int fullBlocks = array.Length / BLOCK_SIZE;
        // Initialize first block
        for (int j = 0; j < BLOCK_SIZE; j++) array[j] = value;
        // Copy successive full blocks
        for (int blk = 1; blk < fullBlocks; blk++)
        {
            Array.Copy(array, 0, array, blk * BLOCK_SIZE, BLOCK_SIZE);
        }

        for (int rem = fullBlocks * BLOCK_SIZE; rem < array.Length; rem++)
        {
            array[rem] = value;
        }
    }
}
Eric J.
fonte
3

Se você planeja definir apenas alguns valores na matriz, mas deseja obter o valor padrão (personalizado) na maior parte do tempo, tente algo como:

public class SparseArray<T>
{
    private Dictionary<int, T> values = new Dictionary<int, T>();

    private T defaultValue;

    public SparseArray(T defaultValue)
    {
        this.defaultValue = defaultValue;
    }

    public T this [int index]
    {
      set { values[index] = value; }
      get { return values.ContainsKey(index) ? values[index] ? defaultValue; }
    }
}

Você provavelmente precisará implementar outras interfaces para torná-lo útil, como as da própria matriz .

Douglas
fonte
3

Não há como definir todos os elementos em uma matriz como uma única operação, a menos que esse valor seja o valor padrão do tipo de elemento.

Por exemplo, se for uma matriz de números inteiros, você poderá configurá-los para zero com uma única operação, da seguinte forma: Array.Clear(...)

James
fonte
2

Sei que estou atrasada para a festa, mas aqui está uma idéia. Escreva um wrapper que possua operadores de conversão de e para o valor agrupado, para que possa ser usado como substituto do tipo agrupado. Na verdade, isso foi inspirado pela resposta boba da @ l33t.

Primeiro (vindo de C ++), percebi que em C # um ctor padrão não é chamado quando os elementos de uma matriz são construídos. Em vez disso - mesmo na presença de um construtor padrão definido pelo usuário! - todos os elementos da matriz são inicializados com zero. Isso me surpreendeu.

Portanto, uma classe de wrapper que simplesmente fornece um ctor padrão com o valor desejado funcionaria para matrizes em C ++, mas não em C #. Uma solução alternativa é permitir que o tipo de invólucro mapeie 0 para o valor inicial desejado na conversão. Dessa forma, os valores inicializados zero parecem ser inicializados com a semente para todos os fins práticos:

public struct MyBool
{
    private bool _invertedValue;

    public MyBool(bool b) 
    {   
        _invertedValue = !b;
    }

    public static implicit operator MyBool(bool b)
    {
        return new MyBool(b);
    }

    public static implicit operator bool(MyBool mb)
    {
        return !mb._invertedValue;
    }

}

static void Main(string[] args)
{
        MyBool mb = false; // should expose false.
        Console.Out.WriteLine("false init gives false: " 
                              + !mb);

        MyBool[] fakeBoolArray = new MyBool[100];

        Console.Out.WriteLine("Default array elems are true: " 
                              + fakeBoolArray.All(b => b) );

        fakeBoolArray[21] = false;
        Console.Out.WriteLine("Assigning false worked: " 
                              + !fakeBoolArray[21]);

        fakeBoolArray[21] = true;
        // Should define ToString() on a MyBool,
        // hence the !! to force bool
        Console.Out.WriteLine("Assigning true again worked: " 
                              + !!fakeBoolArray[21]);
}

Esse padrão é aplicável a todos os tipos de valor. Pode-se, por exemplo, mapear 0 a 4 para ints se a inicialização com 4 for desejada etc.

Eu adoraria fazer um modelo dele como seria possível em C ++, fornecendo o valor inicial como parâmetro de modelo, mas entendo que isso não é possível em C #. Ou eu estou esquecendo de alguma coisa? (É claro que o mapeamento em C ++ não é necessário, porque é possível fornecer um ctor padrão que será chamado para elementos de matriz.)

FWIW, aqui está um equivalente em C ++: https://ideone.com/wG8yEh .

Peter - Restabelecer Monica
fonte
2

Se você pode inverter sua lógica, pode usar o Array.Clear()método para definir a matriz booleana como false.

        int upperLimit = 21;
        double optimizeMe = Math.Sqrt(upperLimit);

        bool[] seiveContainer = new bool[upperLimit];
        Array.Clear(seiveContainer, 0, upperLimit);
superstewie
fonte
2

Se você estiver no .NET Core, .NET Standard> = 2.1, ou depender do pacote System.Memory, também poderá usar o Span<T>.Fill()método:

var valueToFill = 165;
var data = new int[100];

data.AsSpan().Fill(valueToFill);

// print array content
for (int i = 0; i < data.Length; i++)
{
    Console.WriteLine(data[i]);
}

https://dotnetfiddle.net/UsJ9bu

Apollo3zehn
fonte
2

Aqui está outra versão para nós, usuários do Framework abandonados pela Microsoft. É 4 vezes mais rápido que Array.Cleare mais rápido do que a solução da Panos Theof e Eric J de e uma paralela do Petar Petrov - até duas vezes mais rápido para grandes matrizes.

Primeiro, quero apresentar o ancestral da função, porque isso facilita a compreensão do código. Em termos de desempenho, isso é parecido com o código de Panos Theof, e para algumas coisas que já podem ser suficientes:

public static void Fill<T> (T[] array, int count, T value, int threshold = 32)
{
    if (threshold <= 0)
        throw new ArgumentException("threshold");

    int current_size = 0, keep_looping_up_to = Math.Min(count, threshold);

    while (current_size < keep_looping_up_to)
        array[current_size++] = value;

    for (int at_least_half = (count + 1) >> 1; current_size < at_least_half; current_size <<= 1)
        Array.Copy(array, 0, array, current_size, current_size);

    Array.Copy(array, 0, array, current_size, count - current_size);
}

Como você pode ver, isso se baseia na duplicação repetida da parte já inicializada. Isso é simples e eficiente, mas está em conflito com as arquiteturas de memória modernas. Portanto, nasceu uma versão que usa a duplicação apenas para criar um bloco de propagação compatível com cache, que é distribuído iterativamente pela área de destino:

const int ARRAY_COPY_THRESHOLD = 32;  // 16 ... 64 work equally well for all tested constellations
const int L1_CACHE_SIZE = 1 << 15;

public static void Fill<T> (T[] array, int count, T value, int element_size)
{
    int current_size = 0, keep_looping_up_to = Math.Min(count, ARRAY_COPY_THRESHOLD);

    while (current_size < keep_looping_up_to)
        array[current_size++] = value;

    int block_size = L1_CACHE_SIZE / element_size / 2;
    int keep_doubling_up_to = Math.Min(block_size, count >> 1);

    for ( ; current_size < keep_doubling_up_to; current_size <<= 1)
        Array.Copy(array, 0, array, current_size, current_size);

    for (int enough = count - block_size; current_size < enough; current_size += block_size)
        Array.Copy(array, 0, array, current_size, block_size);

    Array.Copy(array, 0, array, current_size, count - current_size);
}

Nota: o código anterior necessário (count + 1) >> 1como limite para o ciclo de duplicação para garantir que a operação de cópia final tenha forragem suficiente para cobrir tudo o que resta. Esse não seria o caso de contagens ímpares, se count >> 1fosse utilizado em seu lugar. Para a versão atual, isso não tem significado, uma vez que o loop de cópia linear receberá qualquer folga.

O tamanho de uma célula de matriz deve ser passado como parâmetro porque - a mente desconcerta - os genéricos não podem usar, a sizeofmenos que usem uma restrição ( unmanaged) que pode ou não estar disponível no futuro. Estimativas erradas não são um grande problema, mas o desempenho é melhor se o valor for preciso, pelos seguintes motivos:

  • Subestimar o tamanho do elemento pode levar a tamanhos de bloco maiores que a metade do cache L1, aumentando a probabilidade de os dados da fonte de cópia serem despejados do L1 e precisando ser buscados novamente a partir de níveis mais lentos do cache.

  • Superestimar o tamanho do elemento resulta na subutilização do cache L1 da CPU, o que significa que o loop de cópia de bloco linear é executado com mais frequência do que seria com a utilização ideal. Assim, ocorre mais sobrecarga de loop / chamada fixa do que o estritamente necessário.

Aqui está uma referência comparando meu código Array.Cleare as outras três soluções mencionadas anteriormente. Os horários são para o preenchimento de matrizes inteiras ( Int32[]) dos tamanhos fornecidos. Para reduzir a variação causada por caprichos no cache, etc., cada teste foi executado duas vezes, consecutivamente, e os tempos foram tomados para a segunda execução.

array size   Array.Clear      Eric J.   Panos Theof  Petar Petrov   Darth Gizka
-------------------------------------------------------------------------------
     1000:       0,7 µs        0,2 µs        0,2 µs        6,8 µs       0,2 µs 
    10000:       8,0 µs        1,4 µs        1,2 µs        7,8 µs       0,9 µs 
   100000:      72,4 µs       12,4 µs        8,2 µs       33,6 µs       7,5 µs 
  1000000:     652,9 µs      135,8 µs      101,6 µs      197,7 µs      71,6 µs 
 10000000:    7182,6 µs     4174,9 µs     5193,3 µs     3691,5 µs    1658,1 µs 
100000000:   67142,3 µs    44853,3 µs    51372,5 µs    35195,5 µs   16585,1 µs 

Se o desempenho desse código não for suficiente, um caminho promissor seria paralelo ao loop de cópia linear (com todos os threads usando o mesmo bloco de origem) ou ao nosso bom e velho amigo P / Invoke.

Nota: a limpeza e o preenchimento de blocos normalmente são feitos por rotinas de tempo de execução que ramificam para código altamente especializado usando instruções MMX / SSE e outras coisas, portanto, em qualquer ambiente decente, basta chamar o respectivo equivalente moral std::memsete garantir níveis de desempenho profissional. IOW, por direitos, a função de biblioteca Array.Cleardeve deixar todas as nossas versões enroladas à mão na poeira. O fato de ser o contrário mostra o quão longe as coisas estão realmente. O mesmo vale para ter que rolar a si próprio Fill<>em primeiro lugar, porque ainda está apenas no Core e no Standard, mas não no Framework. O .NET já existe há quase vinte anos e ainda temos que P / Invocar para a esquerda e para a direita para obter as coisas mais básicas ou ...

DarthGizka
fonte
0

Aqui está outra abordagem com a System.Collections.BitArrayqual tem esse construtor.

bool[] result = new BitArray(1000000, true).Cast<bool>().ToArray();

ou

bool[] result = new bool[1000000];
new BitArray(1000000, true).CopyTo(result, 0);
fubo
fonte
0

Faça uma classe privada dentro de onde você faz a matriz e tenha um getter e setter para ela. A menos que você precise que cada posição na matriz seja algo único, como aleatório, use int? como uma matriz e, em seguida, obtenha se a posição for igual a nula, preencha essa posição e retorne o novo valor aleatório.

IsVisibleHandler
{

  private bool[] b = new bool[10000];

  public bool GetIsVisible(int x)
  {
  return !b[x]
  }

  public void SetIsVisibleTrueAt(int x)
  {
  b[x] = false //!true
  }
}

Ou use

public void SetIsVisibleAt(int x, bool isTrue)
{
b[x] = !isTrue;
}

Como setter.

Peter J
fonte
-2
Boolean[] data = new Boolean[25];

new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);
ldsmithperrin
fonte
Use uma formatação melhor e talvez algumas palavras explicativas para que outras pessoas possam entender melhor sua solução.
Gorgsenegger
1
Você pode usar isso para aumentar o desempenho da inicialização particionando a matriz de destino e copiando a semente para as várias partições. Isso foi apenas para dar uma idéia - Este é o meu primeiro e foi o meu último post na história.
Ldsmithperrin