नेचर फॉरचेट स्टेटमेंट के साथ Iterate मल्टी-डायमेंशनल ऐरे


79

मुझे लगता है कि यह एक बहुत ही सरल प्रश्न हो सकता है, लेकिन मैं अभी तक इसका पता नहीं लगा पाया हूं। अगर मुझे ऐसा 2-आयामी सरणी मिल गया है:

int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} };

नेस्टेड फ़ॉर्वर्ड स्टेटमेंट के साथ एरे के प्रत्येक आयाम के माध्यम से पुनरावृति करने का सबसे अच्छा तरीका क्या है ?


क्या यह दो-आयामी सरणी होना चाहिए, या क्या आप सरणियों के एक सरणी का उपयोग कर सकते हैं?
मैथ्यू फ्लैशेन

जवाबों:


133

यदि आप सरणी में प्रत्येक आइटम पर पुनरावृति करना चाहते हैं जैसे कि यह एक चपटा हुआ सरणी है, तो आप बस कर सकते हैं:

foreach (int i in array) {
    Console.Write(i);
}

जो छपेगा

123456 है

यदि आप x और y इंडेक्स को भी जानना चाहते हैं, तो आपको यह करना होगा:

for (int x = 0; x < array.GetLength(0); x += 1) {
    for (int y = 0; y < array.GetLength(1); y += 1) {
        Console.Write(array[x, y]);
    }
}

वैकल्पिक रूप से आप इसके बजाय दांतेदार सरणी का उपयोग कर सकते हैं (सरणियों का एक सरणी):

int[][] array = new int[2][] { new int[3] {1, 2, 3}, new int[3] {4, 5, 6} };
foreach (int[] subArray in array) {
    foreach (int i in subArray) {
        Console.Write(i);
    }
}

या

int[][] array = new int[2][] { new int[3] {1, 2, 3}, new int[3] {4, 5, 6} };
for (int j = 0; j < array.Length; j += 1) {
    for (int k = 0; k < array[j].Length; k += 1) {
        Console.Write(array[j][k]);
    }
}

1
मेरे तरीकों की गलती को देखने के बाद (जैसे कि दांतेदार सरणी की तरह एक 2 डी सरणी का उपयोग करने की कोशिश कर रहा है), मैं उस सूची के माध्यम से पुनरावृत्त करने का सबसे अच्छा तरीका मानता हूं जैसे आप इसे अपने पहले उदाहरण में रखते हैं। उत्तर से परे जाने और अन्य विकल्प देने की आपकी इच्छा के कारण आपको वोट मिलता है।
टायलर मूर्ति

2-मंद सरणी समतल क्यों है?
सिपो

C # = यह हमेशा सिर्फ काम करता है। कुछ समय बर्बाद करने से पहले C ++ = काम नहीं करेगा।
jw_

21

2-आयामी सरणी में प्रत्येक तत्व का दौरा कैसे करें। क्या यह वही है जिसकी आपको तलाश थी?

for (int i=0;i<array.GetLength(0);i++)
{
    for (int j=0;j<array.GetLength(1);j++)
    {
        int cell = array[i,j];
    }
}

1
मैं एक के लिए उम्मीद कर रही थी foreach कार्यान्वयन, कि यदि संभव है?
टायलर मुरी

6

बहुआयामी सरणियों के साथ, आप तत्वों के माध्यम से पुनरावृति करने के लिए एक ही विधि का उपयोग कर सकते हैं, उदाहरण के लिए:

int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numbers2D)
{
    System.Console.Write("{0} ", i);
}

इस उदाहरण का आउटपुट है:

9 99 3 33 5 55

संदर्भ


जावा में, बहुआयामी सरणियों में सरणी होती है, इसलिए निम्नलिखित कार्य होते हैं:

    int[][] table = {
            { 1, 2, 3 },
            { 4, 5, 6 },
    };
    for (int[] row : table) {
        for (int el : row) {
            System.out.println(el);
        }
    }

3
सी # में बहुरंगी अवधारणाओं के रूप में बहुआयामी और दांतेदार सरणियाँ हैं, जहां int[,]एक 2 आयामी सरणी है, और int[][]सरणियों का एक दांतेदार सरणी है और प्रत्येक दिए गए सरणी को समान लंबाई की आवश्यकता नहीं है। आप आसानी से दांतेदार सरणी पर एक आड़ू कर सकते हैं, लेकिन एक 2 डी सरणी एक ही प्रकार की संरचना नहीं है। किसी भी दर पर, आपका दूसरा स्निपेट इस समस्या के लायक नहीं है, पहला स्निपेट नेस्टेड नहीं है।
एंथनी पेग्राम

4

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन मैंने इसे Google के माध्यम से पाया, और इसके साथ खेलने के बाद मुझे लगता है कि मेरे पास एक आसान समाधान है। अगर मैं गलत हूं तो कृपया इसे इंगित करें, 'क्यूज मैं जानना चाहता हूं, लेकिन यह कम से कम मेरे उद्देश्यों के लिए काम करता है (यह आईसीआर की प्रतिक्रिया के आधार पर है):

for (int x = 0; x < array.GetLength(0); x++)
{
    Console.Write(array[x, 0], array[x,1], array[x,2]);
}

चूंकि दोनों आयाम सीमित हैं, या तो एक साधारण संख्या हो सकती है, और इस प्रकार लूप के लिए नेस्टेड से बचें। मैं मानता हूं कि मैं C # में नया हूं, इसलिए कृपया, यदि ऐसा नहीं करने का कोई कारण है, तो कृपया मुझे बताएं ...


1
यह 2 आयाम की लंबाई मान रहा है। आप इस धारणा को मुश्किल बना रहे हैं कि दूसरे आयाम में हमेशा लंबाई 3 होगी, जो कि हो सकती है या नहीं। यदि यह 3 नहीं है, लेकिन कहते हैं, 50, तो आप बहुत सारे कॉपी / पेस्ट को देख रहे होंगे और अपने कोड को अपठनीय बना सकते हैं। :)
एडम लीयर

@AnnaLear यह धारणा गलत नहीं है कि आप 15x15 स्क्रैबल बोर्ड जैसे एक अच्छी तरह से परिभाषित लंबाई के मैट्रिक्स को प्रोसेस कर रहे हों
Jaycee

3

सी # में 2 डी सरणी खुद को एक नेस्टेड फॉरेक्स के लिए अच्छी तरह से उधार नहीं देती है, यह दांतेदार सरणी (सरणियों का एक सरणी) के बराबर नहीं है। फॉरच का उपयोग करने के लिए आप ऐसा कुछ कर सकते हैं

foreach (int i in Enumerable.Range(0, array.GetLength(0)))
    foreach (int j in Enumerable.Range(0, array.GetLength(1)))
        Console.WriteLine(array[i, j]);

लेकिन आप अभी भी सरणी के लिए इंडेक्स मान के रूप में i और j का उपयोग करेंगे। यदि आप सिर्फ बगीचे की किस्म के forलूप के बदले गए तो पठनीयता बेहतर रूप से संरक्षित होगी ।


1
यह एक क्लासिक, सरल और समझने योग्य निर्माण का एक भयानक उत्परिवर्तन है। यदि आपके कोड में यह है, तो आपको वास्तव में "हे, यह काम करता है, लेकिन यह सोचने की ज़रूरत है कि ... कैसे नहीं?" (मुझे अच्छी तरह पता इस अजगर परिवार में मुहावरेदार है कर रहा हूँ हालांकि -। यह सी # है।)
Rubys

@ दोस्तों, यह पायथन में मुहावरेदार नहीं है। फिर अनुक्रमणिका प्राप्त करना बहुत ही असाध्य है []। यह सीधे मूल्यों पर पुनरावृति करने के लिए मुहावरेदार पायथन है। यह भी ध्यान दें कि पायथन (केवल दांतेदार) में कोई बहुआयामी सरणियाँ या सूचियाँ नहीं हैं।
मैथ्यू फ्लैशेन

@ मैथ्यू: मैं एक और भाषा के साथ अजगर को भ्रमित कर सकता हूं, मैं वास्तव में स्क्रिप्टिंग परिवार में अपने पैरों से अपनी बाहों को नहीं जानता हूं (जो कि अजगर परिवार में मेरा मतलब है, मुझे लगता है)
रूबिस

2

दो तरीके:

  1. सरणी को दांतेदार सरणी के रूप में परिभाषित करें, और नेस्टेड फॉरेक्स का उपयोग करें।
  2. सरणी को सामान्य रूप से परिभाषित करें, और संपूर्ण चीज़ पर फ़ॉर्च का उपयोग करें।

# 2 का उदाहरण:

int[,] arr = { { 1, 2 }, { 3, 4 } };
foreach(int a in arr)
    Console.Write(a);

आउटपुट 1234 होगा। ठीक उसी तरह जैसे कि मैं 0 से n तक कर रहा हूं, और 0 से n तक j।


2

आप इस तरह से एक एक्सटेंशन विधि का उपयोग कर सकते हैं:

internal static class ArrayExt
{
    public static IEnumerable<int> Indices(this Array array, int dimension)
    {
        for (var i = array.GetLowerBound(dimension); i <= array.GetUpperBound(dimension); i++)
        {
            yield return i;
        }
    }
}

और तब:

int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
foreach (var i in array.Indices(0))
{
    foreach (var j in array.Indices(1))
    {
        Console.Write(array[i, j]);
    }

    Console.WriteLine();
}

यह छोरों के लिए उपयोग करने की तुलना में थोड़ा धीमा होगा, लेकिन ज्यादातर मामलों में शायद एक मुद्दा नहीं है। यकीन नहीं होता कि यह चीजों को अधिक पठनीय बनाता है।

ध्यान दें कि c # सरणियाँ शून्य-आधारित के अलावा अन्य हो सकती हैं ताकि आप इस तरह लूप के लिए उपयोग कर सकें:

int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
{
    for (var j= array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
    {
        Console.Write(array[i, j]);
    }

    Console.WriteLine();
}

अजीब ... शून्य-आधारित क्या नहीं है?
drzaus

मुझे लगता है कि मैंने गैर-शून्य-आधारित देखा जब एक्सेल के साथ इंटरोपिंग किया गया, तो यह आम नहीं है लेकिन शायद इसके बारे में पता होना अच्छा है।
जोहान लार्सन

1

जैसा कि कहीं और उल्लेख किया गया है, आप केवल सरणी पर पुनरावृति कर सकते हैं और यह सभी आयामों में क्रम में सभी परिणाम देगा। हालाँकि, यदि आप सूचकांकों को भी जानना चाहते हैं, तो इसका उपयोग कैसे करें - http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with linq.aspx

फिर कुछ कर रहे हैं जैसे:

var dimensionLengthRanges = Enumerable.Range(0, myArray.Rank).Select(x => Enumerable.Range(0, myArray.GetLength(x)));
var indicesCombinations = dimensionLengthRanges.CartesianProduct();

foreach (var indices in indicesCombinations)
{
    Console.WriteLine("[{0}] = {1}", string.Join(",", indices), myArray.GetValue(indices.ToArray()));
}

1

.Cast<int>()2D सरणी को कनवर्ट करने के लिए LINQ का उपयोग करें IEnumerable<int>

LINQPad उदाहरण:

var arr = new int[,] { 
  { 1, 2, 3 }, 
  { 4, 5, 6 } 
};

IEnumerable<int> values = arr.Cast<int>();
Console.WriteLine(values);

आउटपुट:

अनुक्रम 1,2,3,4,5,6 है


0

आप एन्यूमरेटर्स का उपयोग भी कर सकते हैं। किसी भी आयाम का हर प्रकार-प्रकार Array.GetEnumerator विधि का समर्थन करता है। एकमात्र चेतावनी यह है कि आपको बॉक्सिंग / अनबॉक्सिंग से निपटना होगा। हालाँकि, आपको जो कोड लिखना होगा वह काफी तुच्छ होगा।

यहाँ नमूना कोड है:

class Program
{
    static void Main(string[] args)
    {
        int[,] myArray = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
        var e = myArray.GetEnumerator();

        e.Reset();

        while (e.MoveNext())
        {
            // this will output each number from 1 to 6. 
            Console.WriteLine(e.Current.ToString());
        }

        Console.ReadLine();
    }
}

वोट -1 ... मैं Using foreach is recommended, instead of directly manipulating the enumerator.
इवान

0
int[,] arr =  { 
                {1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}
              };
 for(int i = 0; i < arr.GetLength(0); i++){
      for (int j = 0; j < arr.GetLength(1); j++)
           Console.Write( "{0}\t",arr[i, j]);
      Console.WriteLine();
    }

output:  1  2  3
         4  5  6
         7  8  9

0

मैं हर तत्व सूचकांकों तक पहुँच के साथ संकलन समय रैंक पर एक अज्ञात की एक सरणी की गणना करने के लिए एक समाधान की तलाश में था। मैंने पैदावार के साथ समाधान देखा, लेकिन यहाँ कोई और उपज नहीं है। यह पुराने स्कूल में न्यूनतम है। इस उदाहरण में AppendArrayDebug () केवल StringBuilder बफर में सभी तत्वों को प्रिंट करता है।

public static void AppendArrayDebug ( StringBuilder sb, Array array )
{
    if( array == null || array.Length == 0 )
    {
        sb.Append( "<nothing>" );
        return;
    }

    int i;

    var rank = array.Rank;
    var lastIndex = rank - 1;

    // Initialize indices and their boundaries
    var indices = new int[rank];
    var lower = new int[rank];
    var upper = new int[rank];
    for( i = 0; i < rank; ++i )
    {
        indices[i] = lower[i] = array.GetLowerBound( i );
        upper[i] = array.GetUpperBound( i );
    }

    while( true )
    {
        BeginMainLoop:

        // Begin work with an element

        var element = array.GetValue( indices );

        sb.AppendLine();
        sb.Append( '[' );
        for( i = 0; i < rank; ++i )
        {
            sb.Append( indices[i] );
            sb.Append( ' ' );
        }
        sb.Length -= 1;
        sb.Append( "] = " );
        sb.Append( element );

        // End work with the element

        // Increment index set

        // All indices except the first one are enumerated several times
        for( i = lastIndex; i > 0; )
        {
            if( ++indices[i] <= upper[i] )
                goto BeginMainLoop;
            indices[i] = lower[i];
            --i;
        }

        // Special case for the first index, it must be enumerated only once
        if( ++indices[0] > upper[0] )
            break;
    }
}

उदाहरण के लिए निम्न सरणी निम्न आउटपुट का उत्पादन करेगी:

var array = new [,,]
{
    { {  1,  2,  3 }, {  4,  5,  6 }, {  7,  8,  9 }, { 10, 11, 12 } },
    { { 13, 14, 15 }, { 16, 17, 18 }, { 19, 20, 21 }, { 22, 23, 24 } }
};

/*
Output:

[0 0 0] = 1
[0 0 1] = 2
[0 0 2] = 3
[0 1 0] = 4
[0 1 1] = 5
[0 1 2] = 6
[0 2 0] = 7
[0 2 1] = 8
[0 2 2] = 9
[0 3 0] = 10
[0 3 1] = 11
[0 3 2] = 12
[1 0 0] = 13
[1 0 1] = 14
[1 0 2] = 15
[1 1 0] = 16
[1 1 1] = 17
[1 1 2] = 18
[1 2 0] = 19
[1 2 1] = 20
[1 2 2] = 21
[1 3 0] = 22
[1 3 1] = 23
[1 3 2] = 24
*/
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.