2010-07-15 14 views
7

question bien simple, ici (peut-être pas une réponse simple?)Trouver la position d'un élément dans un tableau à deux dimensions?

Dire que j'ai un tableau à deux dimensions

[0] [1] [2] 
[3] [4] [5] 
[6] [7] [8] 

Supposons maintenant que je veux obtenir la position du numéro 6

Je sais avec un tableau unidimensionnel je peux utiliser Array.indexOf() mais quelles seraient mes options avec des tableaux bidimensionnels?

Merci!

+0

Je suppose que vous voulez dire un tableau 2D ('int [,]'), pas un tableau en dents de scie ('int [] []' – SLaks

Répondre

19

Je dirais quelque chose comme ceci:

public static Tuple<int, int> CoordinatesOf<T>(this T[,] matrix, T value) 
{ 
    int w = matrix.GetLength(0); // width 
    int h = matrix.GetLength(1); // height 

    for (int x = 0; x < w; ++x) 
    { 
     for (int y = 0; y < h; ++y) 
     { 
      if (matrix[x, y].Equals(value)) 
       return Tuple.Create(x, y); 
     } 
    } 

    return Tuple.Create(-1, -1); 
} 
+0

Dans des situations comme celle-ci, je préfère créer une classe pour représenter le résultat plutôt que d'utiliser un Tuple puisque Tuple ne transmet pas ce qui est retourné. Bien sûr, quand vous regardez la ligne Tuple coordinate = matrix.CoordinatesOf (5) vous pouvez facilement deviner que c'est une coordonnée/point mais une fois que cette valeur se déplace dans le système, il devient juste un Tuple laissant un mauvais dev pour traquer le source pour apprendre ce que Tuple représente réellement. –

1

Voici une méthode qui devrait trouver un index dans un tableau avec un rang arbitraire.

... Ajouté gamme supérieure/bounds inférieur par rang

public static class Tools 
{ 
    public static int[] FindIndex(this Array haystack, object needle) 
    { 
     if (haystack.Rank == 1) 
      return new[] { Array.IndexOf(haystack, needle) }; 

     var found = haystack.OfType<object>() 
          .Select((v, i) => new { v, i }) 
          .FirstOrDefault(s => s.v.Equals(needle)); 
     if (found == null) 
      throw new Exception("needle not found in set"); 

     var indexes = new int[haystack.Rank]; 
     var last = found.i; 
     var lastLength = Enumerable.Range(0, haystack.Rank) 
            .Aggregate(1, 
             (a, v) => a * haystack.GetLength(v)); 
     for (var rank =0; rank < haystack.Rank; rank++) 
     { 
      lastLength = lastLength/haystack.GetLength(rank); 
      var value = last/lastLength; 
      last -= value * lastLength; 

      var index = value + haystack.GetLowerBound(rank); 
      if (index > haystack.GetUpperBound(rank)) 
       throw new IndexOutOfRangeException(); 
      indexes[rank] = index; 
     } 

     return indexes; 
    } 
} 
+0

Ceci est très propre, mais l'appel de 'ToList' me semble un peu paresseux ... pourquoi copier le contenu entier d'un tableau multidimensionnel à un' List 'seulement pour utiliser' IndexOf'? Vous pouvez écrire le vôtre qui énumère le tableau sur place. –

+0

bon point. Je pensais à ajouter un soutien aux limites de la gamme de toute façon car je vais changer cela. –