C# 어레이를 단일 값으로 채우는/인스턴스하는 방법은 무엇입니까?
C#에서 값 유형의 인스턴스화된 배열은 유형의 기본값(예: bool의 경우 false, int의 경우 0)으로 자동으로 채워집니다.
기본값이 아닌 시드 값으로 배열을 자동으로 채우는 방법이 있습니까?생성 시 또는 이후에 기본 제공되는 메서드(예: Java의 Arrays.fill()))?False 대신 기본적으로 True인 부울 배열을 원한다고 합니다.이를 위한 기본 제공 방법이 있습니까? 아니면 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;
}
배열을 반복하고 각 값을 true로 "재설정"해야 하는 것은 비효율적입니다.이 근처에 뭔가 있나요?어쩌면 모든 가치관을 뒤집어서요?
이 질문을 입력하고 생각해 본 결과, 기본값은 단순히 C#이 배후에서 이러한 개체의 메모리 할당을 처리하는 방식의 결과라고 생각합니다. 따라서 이 작업은 불가능할 것으로 예상됩니다.하지만 저는 여전히 확실히 알고 싶습니다!
Enumerable.Repeat(true, 1000000).ToArray();
프레임워크 방법에 대해서는 잘 모르지만 빠른 도움말을 작성해 주시면 됩니다.
public static void Populate<T>(this T[] arr, T value ) {
for ( int i = 0; i < arr.Length;i++ ) {
arr[i] = value;
}
}
,000개의 어레이로 새 true값:
var items = Enumerable.Repeat<bool>(true, 1000).ToArray(); // Or ToList(), etc.
마찬가지로 정수 시퀀스를 생성할 수 있습니다.
var items = Enumerable.Range(0, 1000).ToArray(); // 0..999
.NET Core 2.0+ 및 .NET Standard 2.1+에서 사용할 수 있습니다.
크기가 가변적인 대규모 어레이의 경우 다음을 사용해야 합니다.
Enumerable.Repeat(true, 1000000).ToArray();
작은 배열의 경우 C# 3의 컬렉션 초기화 구문을 사용할 수 있습니다.
bool[] vals = new bool[]{ false, false, false, false, false, false, false };
컬렉션 초기화 구문의 이점은 각 슬롯에서 동일한 값을 사용할 필요가 없고 식이나 함수를 사용하여 슬롯을 초기화할 수 있다는 것입니다.또한 어레이 슬롯을 기본값으로 초기화하는 비용을 피할 수 있다고 생각합니다.예를 들어, 다음과 같습니다.
bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };
어레이가 너무 크면 BitArray를 사용해야 합니다.모든 부울에 대해 바이트 대신 1비트를 사용하며(예: 부울 배열), 비트 연산자를 사용하여 모든 비트를 true로 설정할 수 있습니다.또는 true로 초기화합니다.하지만 한 번만 하면 된다면 비용이 더 들 뿐입니다.
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);
2은 .NET Core 2.0을 지원합니다.Array.Fill()방법.
여기 샘플 코드가 있습니다.
var arr = new int[10];
int defaultValue = 2;
Array.Fill(arr,defaultValue);
또한 채워질 인덱스 범위에 대한 오버로드 방법도 있습니다.자세한 내용은 여기에서 확인할 수 있습니다.
유감스럽게도 직접적인 방법은 없다고 생각하지만, 어레이 클래스에 대한 확장 방법을 작성하여 이를 수행할 수 있다고 생각합니다.
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;
}
}
}
조금 더 검색하고 읽은 후에 저는 다음을 발견했습니다.
bool[] bPrimes = new bool[1000000];
bPrimes = Array.ConvertAll<bool, bool>(bPrimes, b=> b=true);
제가 찾고 있는 것과 확실히 더 가깝습니다.하지만 for-loop의 원래 배열을 반복하고 값을 변경하는 것보다 더 나은지는 잘 모르겠습니다.실제로 빠른 테스트를 실시한 결과, 약 5배 정도 더 느리게 나타납니다.그렇다면 좋은 해결책은 아닙니다!
아래 코드는 작은 복사본과 배열에 대한 단순 반복을 결합한 것입니다.대용량 복사본의 경우 복사본
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;
}
}
}
int[] 어레이를 사용하는 다양한 어레이 길이의 벤치마크는 다음과 같습니다.
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
첫 번째 열은 배열 크기이고, 그 다음에 간단한 반복을 사용하여 복사하는 시간입니다(@JaredPared 구현).이 방법의 시간은 그 이후입니다.이것들은 4개의 정수 구조의 배열을 사용하는 벤치마크입니다.
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
. Core, . Standard > = 또는 .NET Core, .NET Standard > = 2.1 또는 시스템에 의존하는 경우.메리패사수있다습니도용할을 도 있습니다.Span<T>.Fill()방법:
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
병렬 구현은 어떻습니까?
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);
}
배열을 초기화할 때만 이 코드의 힘을 볼 수는 없지만 "순수"에 대해서는 분명히 잊어야 한다고 생각합니다.
아니면... 단순히 역논리를 사용할 수도 있습니다.허락하다false의미하다true그리고 역도 성립.
코드샘플
// 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!
}
여기에 제시된 많은 답변은 한 번에 하나의 요소를 어레이를 초기화하는 루프로 요약됩니다. 이 루프는 메모리 블록에서 한 번에 작동하도록 설계된 CPU 명령을 활용하지 않습니다.
.Net Standard 2.1(본 문서의 미리 보기)은 어레이를 제공합니다.Fill()은 런타임 라이브러리의 고성능 구현에 적합합니다(그러나 현재로서는 .NET Core가 이러한 가능성을 활용하지 않는 것 같습니다).
이전 플랫폼의 경우, 다음 확장 방법은 어레이 크기가 상당할 때 사소한 루프보다 성능이 훨씬 뛰어납니다.온라인 코드 챌린지에 대한 제 솔루션이 할당된 시간 예산보다 20% 정도 초과되었을 때 이를 만들었습니다.실행 시간을 약 70% 단축했습니다.이 경우 어레이 채우기는 다른 루프 내에서 수행되었으며 BLOCK_SIZE는 실험이 아닌 gut feel에 의해 설정되었습니다.일부 최적화는 가능합니다(예: 고정 크기 블록이 아닌 이미 설정된 모든 바이트를 원하는 값으로 복사).
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;
}
}
}
단순한 벤치마크:
BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.997 (1909/November2018Update/19H2)
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.302
[Host] : .NET Core 3.1.6 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.31603), X64 RyuJIT
.NET Core 3.1 : .NET Core 3.1.6 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.31603), X64 RyuJIT
Job=.NET Core 3.1 Runtime=.NET Core 3.1
| Method | Mean | Error | StdDev |
|----------------- |---------:|----------:|----------:|
| EnumerableRepeat | 2.311 us | 0.0228 us | 0.0213 us |
| NewArrayForEach | 2.007 us | 0.0392 us | 0.0348 us |
| ArrayFill | 2.426 us | 0.0103 us | 0.0092 us |
[SimpleJob(BenchmarkDotNet.Jobs.RuntimeMoniker.NetCoreApp31)]
public class InitializeArrayBenchmark {
const int ArrayLength = 1600;
[Benchmark]
public double[] EnumerableRepeat() {
return Enumerable.Repeat(double.PositiveInfinity, ArrayLength).ToArray();
}
[Benchmark]
public double[] NewArrayForEach() {
var array = new double[ArrayLength];
for (int i = 0; i < array.Length; i++) {
array[i] = double.PositiveInfinity;
}
return array;
}
[Benchmark]
public double[] ArrayFill() {
var array = new double[ArrayLength];
Array.Fill(array, double.PositiveInfinity);
return array;
}
}
이것도 효과가 있습니다...하지만 불필요할 수도 있습니다.
bool[] abValues = new bool[1000];
abValues = abValues.Select( n => n = true ).ToArray<bool>();
배열의 모든 요소를 단일 작업으로 설정할 수 있는 방법은 없습니다. 단, 해당 값이 요소 유형 기본값입니다.
할 수 : 예 들 어 배 경 으 다 인 같 우 과 한 연 번 있 수 습 니 다 모 산 설 로 할 정 정 으 의 두 를 이 수 로 음 열 , ▁eg ▁youArray.Clear(...)
여기 마이크로소프트가 포기한 프레임워크 사용자를 위한 다른 버전이 있습니다.Panos Theof의 솔루션과 Eric J's 및 Petar Petrov의 병렬 솔루션보다 4배 빠르고, 대규모 어레이의 경우 최대 2배 빠릅니다.
먼저 함수의 조상을 소개하겠습니다. 왜냐하면 코드를 이해하는 것이 더 쉽기 때문입니다.성능 측면에서 이는 Panos Theof의 코드와 거의 비슷하며 이미 충분할 수도 있습니다.
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);
}
보시다시피, 이는 이미 초기화된 부품을 반복적으로 두 배로 늘리는 것을 기반으로 합니다.이것은 간단하고 효율적이지만 현대적인 메모리 아키텍처에 위배됩니다.따라서 더블링만 사용하여 캐시 친화적인 시드 블록을 생성한 다음 대상 영역에서 반복적으로 블래칭하는 버전이 탄생했습니다.
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);
}
참고: 이전 코드가 필요했습니다.(count + 1) >> 1더블링 루프에 대한 제한으로 최종 복사 작업이 남은 모든 것을 커버할 수 있는 충분한 피드를 확보합니다.홀수 카운트의 경우 다음과 같은 경우에는 그렇지 않습니다.count >> 1대신 사용하기로 했습니다.현재 버전에서는 선형 복사 루프가 느슨한 부분을 포착하기 때문에 이는 중요하지 않습니다.
배열 셀의 크기는 매개 변수로 전달되어야 합니다. 이는 - mindboggle - 제네릭이 나중에 사용할 수 있거나 사용할 수 없게 unmanaged될 수 있는 제약 조건()을 사용하지 않는 한 사용할 수 없기 때문입니다.잘못된 추정치는 큰 문제가 아니지만 다음과 같은 이유로 값이 정확할 경우 성능이 가장 좋습니다.
요소 크기를 과소평가하면 블록 크기가 L1 캐시의 절반보다 클 수 있으므로 L1에서 복사 소스 데이터가 제거되고 느린 캐시 수준에서 다시 가져와야 할 가능성이 높아집니다.
요소 크기를 과대평가하면 CPU의 L1 캐시 활용도가 낮아집니다. 즉, 선형 블록 복사 루프가 최적 활용도보다 더 자주 실행됩니다.따라서 고정 루프/통화 오버헤드는 엄격하게 필요한 것보다 더 많이 발생합니다.
다음은 내 코드와 경쟁하는 벤치마크입니다.Array.Clear그리고 앞에서 언급한 다른 세 가지 해결책.배열을 입니다.Int32[]캐시변등인로변줄위니다입해서이기을동한으화▁▁was▁. 각 테스트는 두 연속으로 되었고, 두 .각 테스트는 연속적으로 두 번 실행되었으며 두 번째 실행에 대한 시간이 소요되었습니다.
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
만약 이 코드의 성능이 충분하지 않다면 유망한 방법은 선형 복사 루프(모든 스레드가 동일한 소스 블록을 사용함) 또는 우리의 오랜 친구 P/Invoke를 병렬화하는 것입니다.
및으로 MMX 환경에서는 ": 블참지고채우것고우는은일명반으적로록을사고 MMX/▁the▁note▁callive▁moral▁simply▁using▁is▁routines참▁that▁ofent▁would▁clearing고ment▁ofnot▁one▁decent▁blocks수의루x▁fillings,런로▁environ,▁so▁and▁runtimeions므되해▁highly행:▁any에▁to▁by 적절한 환경에서는 단순히 각각의 도덕적 동등성이라고 할 수 있습니다.std::memset전문적인 수준의 성능을 보장합니다.IOW, 권한에 따라 라이브러리 기능Array.Clear손으로 말아서 만든 것들은 모두 먼지 속에 남겨두어야 합니다.그것이 그 반대라는 사실은 상황이 실제로 얼마나 터무니없는 것인지 보여줍니다.자신의 것을 굴려야 하는 것도 마찬가지입니다.Fill<>첫째, 아직 Core와 Standard에만 있지만 Framework에는 없기 때문입니다. .NET은 거의 20년 동안 존재해 왔으며 여전히 가장 기본적인 것들을 위해 왼쪽과 오른쪽으로 P/Invoke를 하거나 우리만의 것을 굴려야 합니다.
배열에서 몇 개의 값만 설정할 계획이지만 대부분의 경우 (사용자 지정) 기본값을 사용하려면 다음과 같은 방법을 사용할 수 있습니다.
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; }
}
}
어레이 자체와 같이 다른 인터페이스를 구현하여 유용하게 사용해야 할 수도 있습니다.
저는 아무도 매우 간단하면서도 매우 빠른 SIMD 버전을 만들지 않았다는 것에 약간 놀랐습니다.
public static void PopulateSimd<T>(T[] array, T value) where T : struct
{
var vector = new Vector<T>(value);
var i = 0;
var s = Vector<T>.Count;
var l = array.Length & ~(s-1);
for (; i < l; i += s) vector.CopyTo(array, i);
for (; i < array.Length; i++) array[i] = value;
}
벤치마크: (Framework 4.8의 수치이지만 Core 3.1은 통계적으로 동일합니다.)
방법 | N | 평균 | 오차 | 표준 편차 | 비율 | 비율SD ||----------- |-------- |---------------:|---------------:|--------------:|------:|--------:|다스 기즈카 | 10 | 25.975 ns | 1.2430 ns | 0.1924 ns | 1.00 | 0.00 |심드 | 10 | 3.438 ns | 0.4427 ns | 0.0685 ns | 0.13 | 0.00 || | | | | | | |다스 기즈카 | 100 | 81.155ns | 3.8287ns | 0.2099ns | 1.00 | 0.00ns |심드 | 100 | 12.178 ns | 0.4547 ns | 0.0704 ns | 0.15 | 0.00 || | | | | | | |다스 기즈카 | 1000 | 201.138 ns | 8.9769 ns | 1.3892 ns | 1.00 | 0.00 |심드 | 1000 | 100.397 ns | 4.0965 ns | 0.6339 ns | 0.50 | 0.00 || | | | | | | |다스 기즈카 | 10000 | 1,292.660 ns | 38.4965 ns | 5.9574 ns | 1.00 | 0.00 |심드 | 10000 | 1,272.819 ns | 68.5148 ns | 10.6027 ns | 0.98 | 0.01 || | | | | | | |다스 기즈카 | 100000 | 16,156.106 ns | 366.1133 ns | 56.6564 ns | 1.00 | 0.00 |심드 | 100000 | 17,627.879 ns | 1,589.7423 ns | 246.0144 ns | 1.09 | 0.02 || | | | | | | |DarthGizka | 1000000 | 176,625.870 ns | 32,235.9957 ns | 1,766.9637 ns | 1.00 | 0.00 |심드 | 1000000 | 186,812.920 ns | 18,069.1517 ns | 2,796.2212 ns | 1.07 | 0.01 |
볼 수 있듯이, 그것은 <10000개의 원소들>에서 훨씬 더 빠르며, 그 이상으로 약간 느릴 뿐입니다.
제가 파티에 늦었다는 것은 알지만 여기 아이디어가 있습니다.랩핑된 값으로 변환 연산자가 있는 래퍼를 작성하여 랩핑된 유형의 스탠드인으로 사용할 수 있도록 합니다.이것은 실제로 @l33t의 바보 같은 대답에서 영감을 받았습니다.
먼저 (C++에서 온) C#에서 배열의 요소가 구성될 때 기본 벡터가 호출되지 않는다는 것을 깨달았습니다.대신 사용자 정의 기본 생성자가 있는 경우에도 모든 배열 요소가 초기화되지 않습니다.깜짝 놀랐어요.
따라서 단순히 원하는 값의 기본 cctor를 제공하는 래퍼 클래스는 C++의 배열에서는 작동하지만 C#에서는 작동하지 않습니다.해결 방법은 변환 시 래퍼 유형 0이 원하는 시드 값에 매핑되도록 하는 것입니다.이러한 방식으로 제로 초기화 값은 모든 실용적인 목적을 위해 시드와 함께 초기화되는 것으로 보입니다.
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]);
}
이 패턴은 모든 값 유형에 적용됩니다.예를 들어 4로 초기화를 원하는 경우 int에 대해 0부터 4까지 매핑할 수 있습니다.
시드 값을 템플릿 매개 변수로 제공하여 C++에서 가능한 대로 템플릿을 만들고 싶지만 C#에서는 불가능한 것으로 알고 있습니다.아니면 제가 뭔가를 놓치고 있는 것일까요? (물론 C++ 매핑에서는 배열 요소에 대해 호출될 기본 cctor를 제공할 수 있기 때문에 전혀 필요하지 않습니다.)
FWIW, 여기 C++에 해당하는 것이 있습니다: https://ideone.com/wG8yEh .
논리를 뒤집을 수 있는 경우 다음을 사용할 수 있습니다.Array.Clear()부울 배열을 false로 설정하는 메서드입니다.
int upperLimit = 21;
double optimizeMe = Math.Sqrt(upperLimit);
bool[] seiveContainer = new bool[upperLimit];
Array.Clear(seiveContainer, 0, upperLimit);
이에 대한 답변이 몇 가지 더 있습니다(복사본?).질문:.C#에서 memset에 해당하는 것은 무엇입니까?
누군가가 대안을 벤치마킹했습니다(안전하지 않은 버전을 포함했지만 시도하지 않았습니다).memset): http://techmikael.blogspot.co.uk/2009/12/filling-array-with-default-value.html
다음은 에 대한 또 다른 평가입니다.System.Collections.BitArray그런 생성자를 가진.
bool[] result = new BitArray(1000000, true).Cast<bool>().ToArray();
또는
bool[] result = new bool[1000000];
new BitArray(1000000, true).CopyTo(result, 0);
배열을 만드는 내부에 개인 클래스를 만들고 이를 위한 getter와 setter를 만듭니다.배열의 각 위치가 임의와 같이 고유한 것이어야 하는 경우를 제외하고 int?를 배열로 사용한 다음 위치가 동일한 null이면 해당 위치를 채우고 새 임의 값을 반환합니다.
IsVisibleHandler
{
private bool[] b = new bool[10000];
public bool GetIsVisible(int x)
{
return !b[x]
}
public void SetIsVisibleTrueAt(int x)
{
b[x] = false //!true
}
}
또는 사용
public void SetIsVisibleAt(int x, bool isTrue)
{
b[x] = !isTrue;
}
세터.
Boolean[] data = new Boolean[25];
new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);
언급URL : https://stackoverflow.com/questions/1014005/how-to-populate-instantiate-a-c-sharp-array-with-a-single-value
'programing' 카테고리의 다른 글
| NodeJS에서 의존성 주입이 필요합니까? 아니면 ...을 처리하는 방법이 필요합니까? (0) | 2023.05.22 |
|---|---|
| 제안/자동 완성을 통한 Excel 데이터 검증 (0) | 2023.05.22 |
| xsd에서 .NET 4.0 클래스를 생성하는 방법은 무엇입니까? (0) | 2023.05.22 |
| 인증서 서명 요청을 얻는 방법 (0) | 2023.05.22 |
| 목록: 카운트 대 카운트() (0) | 2023.05.22 |