Dizinler ve aralıklar
Aralıklar ve dizinler, bir dizideki tek öğelere veya aralıklara erişmek için kısa bir söz dizimi sağlar.
Bu öğreticide aşağıdakilerin nasıl yapılacağını öğreneceksiniz:
Dizinler ve aralıklar için dil desteği
Dizinler ve aralıklar, bir dizideki tek öğelere veya aralıklara erişmek için kısa bir söz dizimi sağlar.
Bu dil desteği iki yeni türe ve iki yeni işleçe dayanır:
- System.Index bir dizinin dizisini temsil eder.
- End işlecinden
^
dizin, dizinin bir dizinin bir dizinin sonuna göre olduğunu belirtir. - System.Range bir dizinin alt aralığını temsil eder.
- Bir aralığın başlangıç ve bitişini işlenenleri olarak belirten aralık işleci
..
.
Dizinler için kurallarla başlayalım. bir dizi sequence
düşünün. Dizin 0
ile aynıdır sequence[0]
. Dizin ^0
ile aynıdır sequence[sequence.Length]
. İfade sequence[^0]
, tıpkı olduğu gibi sequence[sequence.Length]
bir özel durum oluşturur. herhangi bir sayı n
için dizin ^n
ile aynıdır sequence.Length - n
.
string[] words = [
// index from start index from end
"The", // 0 ^9
"quick", // 1 ^8
"brown", // 2 ^7
"fox", // 3 ^6
"jumps", // 4 ^5
"over", // 5 ^4
"the", // 6 ^3
"lazy", // 7 ^2
"dog" // 8 ^1
]; // 9 (or words.Length) ^0
Dizinle birlikte ^1
son sözcüğü alabilirsiniz. Başlatmanın altına aşağıdaki kodu ekleyin:
Console.WriteLine($"The last word is {words[^1]}");
Aralık, aralığın başlangıcını ve sonunu belirtir. Aralığın başlangıcı kapsayıcıdır, ancak aralığın sonu özeldir; bu, başlangıcın aralığa dahil olduğu ancak sonun aralığa dahil olmadığı anlamına gelir. Aralık [0..^0]
, aralığın tamamını temsil ettiği gibi [0..sequence.Length]
aralığın tamamını da temsil eder.
Aşağıdaki kod "quick", "brown" ve "fox" sözcükleriyle bir alt düzen oluşturur. aracılığıyla words[3]
içerirwords[1]
. öğesi words[4]
aralıkta değil.
string[] quickBrownFox = words[1..4];
foreach (var word in quickBrownFox)
Console.Write($"< {word} >");
Console.WriteLine();
Aşağıdaki kod , "lazy" ve "dog" ile aralığı döndürür. ve words[^1]
içerirwords[^2]
. Bitiş dizini words[^0]
dahil değildir. Aşağıdaki kodu da ekleyin:
string[] lazyDog = words[^2..^0];
foreach (var word in lazyDog)
Console.Write($"< {word} >");
Console.WriteLine();
Aşağıdaki örneklerde başlangıç, bitiş veya her ikisi için açık uçlu aralıklar oluşturulur:
string[] allWords = words[..]; // contains "The" through "dog".
string[] firstPhrase = words[..4]; // contains "The" through "fox"
string[] lastPhrase = words[6..]; // contains "the", "lazy" and "dog"
foreach (var word in allWords)
Console.Write($"< {word} >");
Console.WriteLine();
foreach (var word in firstPhrase)
Console.Write($"< {word} >");
Console.WriteLine();
foreach (var word in lastPhrase)
Console.Write($"< {word} >");
Console.WriteLine();
Aralıkları veya dizinleri değişken olarak da bildirebilirsiniz. Değişkeni daha sonra ve ]
karakterlerinin [
içinde kullanılabilir:
Index the = ^3;
Console.WriteLine(words[the]);
Range phrase = 1..4;
string[] text = words[phrase];
foreach (var word in text)
Console.Write($"< {word} >");
Console.WriteLine();
Aşağıdaki örnekte bu seçeneklerin birçok nedeni gösterilmiştir. Farklı birleşimleri denemek için , y
ve z
değerlerini değiştirinx
. Deneme yaparken, geçerli birleşimler x
için değerinden küçük y
ve y
değerinden z
küçük değerleri kullanın. Aşağıdaki kodu yeni bir yönteme ekleyin. Farklı birleşimleri deneyin:
int[] numbers = [..Enumerable.Range(0, 100)];
int x = 12;
int y = 25;
int z = 36;
Console.WriteLine($"{numbers[^x]} is the same as {numbers[numbers.Length - x]}");
Console.WriteLine($"{numbers[x..y].Length} is the same as {y - x}");
Console.WriteLine("numbers[x..y] and numbers[y..z] are consecutive and disjoint:");
Span<int> x_y = numbers[x..y];
Span<int> y_z = numbers[y..z];
Console.WriteLine($"\tnumbers[x..y] is {x_y[0]} through {x_y[^1]}, numbers[y..z] is {y_z[0]} through {y_z[^1]}");
Console.WriteLine("numbers[x..^x] removes x elements at each end:");
Span<int> x_x = numbers[x..^x];
Console.WriteLine($"\tnumbers[x..^x] starts with {x_x[0]} and ends with {x_x[^1]}");
Console.WriteLine("numbers[..x] means numbers[0..x] and numbers[x..] means numbers[x..^0]");
Span<int> start_x = numbers[..x];
Span<int> zero_x = numbers[0..x];
Console.WriteLine($"\t{start_x[0]}..{start_x[^1]} is the same as {zero_x[0]}..{zero_x[^1]}");
Span<int> z_end = numbers[z..];
Span<int> z_zero = numbers[z..^0];
Console.WriteLine($"\t{z_end[0]}..{z_end[^1]} is the same as {z_zero[0]}..{z_zero[^1]}");
Yalnızca diziler dizinleri ve aralıkları desteklemez. Dizinleri ve aralıkları dize, Span<T>veya ReadOnlySpan<T>ile de kullanabilirsiniz.
Örtük aralık işleci ifade dönüştürmeleri
Aralık işleci ifadesinin söz dizimini kullanırken, derleyici başlangıç ve bitiş değerlerini örtük olarak ve Index değerlerine dönüştürür, yeni Range bir örnek oluşturur. Aşağıdaki kod, aralık işleci ifadesinin söz diziminden örnek örtük dönüştürmeyi ve buna karşılık gelen açık alternatifi gösterir:
Range implicitRange = 3..^5;
Range explicitRange = new(
start: new Index(value: 3, fromEnd: false),
end: new Index(value: 5, fromEnd: true));
if (implicitRange.Equals(explicitRange))
{
Console.WriteLine(
$"The implicit range '{implicitRange}' equals the explicit range '{explicitRange}'");
}
// Sample output:
// The implicit range '3..^5' equals the explicit range '3..^5'
Önemli
değeri negatif olduğunda'dan Int32Index oluşturmaya ArgumentOutOfRangeException yönelik örtük dönüştürmeler. Benzer şekilde, Index
parametre negatif olduğunda value
oluşturucu bir ArgumentOutOfRangeException
oluşturur.
Dizinler ve aralıklar için tür desteği
Dizinler ve aralıklar, tek bir öğeye veya bir dizideki öğe aralığına erişmek için net, kısa söz dizimi sağlar. Dizin ifadesi genellikle bir dizinin öğelerinin türünü döndürür. Aralık ifadesi genellikle kaynak diziyle aynı dizi türünü döndürür.
Veya Range parametresine sahip bir dizin oluşturucu sağlayan herhangi bir Indextür, sırasıyla dizinleri veya aralıkları açıkça destekler. Tek Range bir parametre alan dizin oluşturucu, gibi System.Span<T>farklı bir dizi türü döndürebilir.
Önemli
Aralık işlecini kullanan kodun performansı, sıra işleneninin türüne bağlıdır.
Aralık işlecinin zaman karmaşıklığı sıra türüne bağlıdır. Örneğin, dizi bir string
veya diziyse, sonuç girişin belirtilen bölümünün bir kopyasıdır, bu nedenle zaman karmaşıklığı O(N) olur (burada N aralığın uzunluğudur). Öte yandan, veya iseSystem.Span<T>, sonuç aynı yedekleme deposuna başvurur; başka bir deyişle kopya yoktur ve işlem O(1)'dir.System.Memory<T>
Bu, zaman karmaşıklığının yanı sıra ek ayırmalara ve kopyalara neden olarak performansı etkiler. Performansa duyarlı kodda, aralık işleci bunlar için ayırmadığından sıra türü olarak veya Memory<T>
kullanmayı Span<T>
göz önünde bulundurun.
türü, adlı veya erişilebilir bir alıcıya ve dönüş türüne int
sahip bir özelliği varsa sayılabilir.Count
Length
Dizinleri veya aralıkları açıkça desteklemeyen sayılabilir bir tür, bunlar için örtük bir destek sağlayabilir. Daha fazla bilgi için özellik teklifi notunun Örtük Dizin desteği ve Örtük Aralık desteği bölümlerine bakın. Örtük aralık desteği kullanan aralıklar, kaynak diziyle aynı dizi türünü döndürür.
Örneğin, aşağıdaki .NET türleri hem dizinleri hem de aralıkları destekler: String, Span<T>ve ReadOnlySpan<T>. dizinleri List<T> destekler ancak aralıkları desteklemez.
Array daha fazla nüanslı davranışa sahiptir. Tek boyutlu diziler hem dizinleri hem de aralıkları destekler. Çok boyutlu diziler dizin oluşturucuları veya aralıkları desteklemez. Çok boyutlu bir dizinin dizin oluşturucusunun tek bir parametre değil, birden çok parametresi vardır. Dizi dizisi olarak da adlandırılan pürüzlü diziler hem aralıkları hem de dizin oluşturucuları destekler. Aşağıdaki örnekte, pürüzlü bir dizinin dikdörtgen alt bölümü nasıl yinelenir gösterilmektedir. İlk ve son üç satırı ve seçilen her satırdaki ilk ve son iki sütunu hariç tutarak ortadaki bölümü yineler:
int[][] jagged =
[
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10,11,12,13,14,15,16,17,18,19],
[20,21,22,23,24,25,26,27,28,29],
[30,31,32,33,34,35,36,37,38,39],
[40,41,42,43,44,45,46,47,48,49],
[50,51,52,53,54,55,56,57,58,59],
[60,61,62,63,64,65,66,67,68,69],
[70,71,72,73,74,75,76,77,78,79],
[80,81,82,83,84,85,86,87,88,89],
[90,91,92,93,94,95,96,97,98,99],
];
var selectedRows = jagged[3..^3];
foreach (var row in selectedRows)
{
var selectedColumns = row[2..^2];
foreach (var cell in selectedColumns)
{
Console.Write($"{cell}, ");
}
Console.WriteLine();
}
Her durumda, için Array aralık işleci döndürülen öğeleri depolamak için bir dizi ayırır.
Dizinler ve aralıklar için senaryolar
Daha büyük bir sıranın bir bölümünü analiz etmek istediğinizde genellikle aralıkları ve dizinleri kullanırsınız. Yeni söz dizimi, dizinin tam olarak hangi bölümünün dahil olduğunu okurken daha nettir. Yerel işlev MovingAverage
bağımsız değişkeni olarak bir Range alır. Yöntemi daha sonra min, max ve average değerlerini hesaplarken yalnızca bu aralığı numaralandırır. Projenizde aşağıdaki kodu deneyin:
int[] sequence = Sequence(1000);
for(int start = 0; start < sequence.Length; start += 100)
{
Range r = start..(start+10);
var (min, max, average) = MovingAverage(sequence, r);
Console.WriteLine($"From {r.Start} to {r.End}: \tMin: {min},\tMax: {max},\tAverage: {average}");
}
for (int start = 0; start < sequence.Length; start += 100)
{
Range r = ^(start + 10)..^start;
var (min, max, average) = MovingAverage(sequence, r);
Console.WriteLine($"From {r.Start} to {r.End}: \tMin: {min},\tMax: {max},\tAverage: {average}");
}
(int min, int max, double average) MovingAverage(int[] subSequence, Range range) =>
(
subSequence[range].Min(),
subSequence[range].Max(),
subSequence[range].Average()
);
int[] Sequence(int count) => [..Enumerable.Range(0, count).Select(x => (int)(Math.Sqrt(x) * 100))];
Aralık Dizinleri ve Dizileriyle ilgili Bir Not
Bir diziden aralık alınırken, sonuç başvurulmak yerine ilk diziden kopyalanan bir dizidir. Sonuçta elde edilen dizideki değerlerin değiştirilmesi, ilk dizideki değerleri değiştirmez.
Örneğin:
var arrayOfFiveItems = new[] { 1, 2, 3, 4, 5 };
var firstThreeItems = arrayOfFiveItems[..3]; // contains 1,2,3
firstThreeItems[0] = 11; // now contains 11,2,3
Console.WriteLine(string.Join(",", firstThreeItems));
Console.WriteLine(string.Join(",", arrayOfFiveItems));
// output:
// 11,2,3
// 1,2,3,4,5