2017-11-16 122 views
5

To jest pytanie, które było bardzo trudne do tytułowania.Znajdź na liście wszystkie tablice, których pierwszy element jest taki sam, jak te, które pasują do warunku.

W języku C#, mam zestaw tablic int[,] przechowywanych w List<int[,]> paths, z których każdy trzyma zestaw współrzędnych w celu utworzenia ścieżki. Przykładem może być { {0,0}, {0,1}, {1,1}, {2,1} }.

Teraz chcę zachować w paths wszystkie ścieżki, które mają ten sam pierwszy indeks jako jeden z pierwszych indeksów wszystkich ścieżek, które pasują do warunku.

Aby lepiej wykazać co mam na myśli, powiedzmy mam wszystkie ścieżki, które są o nieparzystej długości:

paths.Where(x => x.GetLength(0) % 2 == 1).ToList(); 

Powiedzmy to zwraca listę zawierającą jakieś tablice, których pierwszy koordy są albo {0,0} lub {0,1} na przykład. Chcę, aby pierwsze współrzędne były następujące: {0,0} lub {0,1} ). Jak mogę to osiągnąć?

Mam nadzieję, że to, co mam na myśli, jest zrozumiałe.

+2

skoro są to ścieżki i zawsze miałbyś 2, czy rozważałeś posiadanie klasy współrzędnych z dwoma właściwościami? –

+0

masz na myśli coś w rodzaju 'x [0] [0] == 0 && x [0] [1] == 1'? –

+0

@NevilleNazerane, który nie byłby najlepszy, gdyby była inna opcja, ponieważ już używałem tej listy 'path' w innych częściach kodu, ponieważ jest to –

Odpowiedz

0

Jak to:

var filteredPaths = paths.Where(x => x[0, 0] == 0 && x[0, 1] == 0 || x[0, 0] == 0 && x[0, 1] == 1); 

Lub jeśli wolisz, aby kontynuować pracę z tym samym typem kolekcji:

List<int[,]> filteredPaths = paths.Where(x => x[0, 0] == 0 && x[1, 0] == 0 || x[0, 0] == 0 && x[1, 0] == 1).ToList(); 
0

Oto jeden się do tego zabrać, zakładając poniższej listy reprezentuje swoich wielowymiarowych elementów :

List<short[,]> paths = new List<short[,]> 
        { 
         new short[3, 2] { { 0, 0 }, { 4, 5 }, { 6, 7 } }, 
         new short[3, 2] { { 0, 1 }, { 8, 9 }, { 10, 11 } }, 
         new short[3, 2] { { 1, 1 }, { 1, 3 } ,{ 6, 1 } }, 
         new short[3, 2] { { 2, 1 }, { 3, 5 }, { 7, 7 } } 
        }; 

zdefiniować kryteria tj .:

short[,] firstCriteria = new short[1, 2] { { 0, 0 } }; 
short[,] secondCriteria = new short[1, 2] { { 0, 1 } }; 

określić metodę rozszerzenia, które powinny umożliwić nam skróconej wielowymiarowej tablicy tylko pierwszych współrzędnych do filtrowania tylko.

static class Helper 
{ 
     public static IEnumerable<short> SliceRow(this short[,] array, short row) 
     { 
      for (var i = array.GetLowerBound(1); i <= array.GetUpperBound(1); i++) 
      { 
       yield return array[row, i]; 
      } 
     } 
} 

następnie można zrobić:

var resutSet = 
      paths.Where(e => e.SliceRow(0).SequenceEqual(firstCriteria.Cast<short>()) || 
        e.SliceRow(0).SequenceEqual(secondCriteria.Cast<short>())).ToList(); 

resultSet będzie teraz zawierać dwa wielowymiarowych tablic, które spełniają podane kryteria tj

{ { 0, 0 }, { 4, 5 }, { 6, 7 } , 
    { 0, 1 }, { 8, 9 }, { 10, 11 } } 
1

Jeśli jesteś ustawiony na korzystanie z aktualnych danych strukturę, możesz to zrobić, ale składnia nie będzie ładna. Zasadniczo przypomina to to, co A. Milto zasugerował w swojej odpowiedzi, z wyjątkiem tego, że potrzebujesz sprawdzania granic, aby uniknąć wyrzucenia wyjątku w przypadku pustej ścieżki. Więc jeśli zdefiniować ścieżki tak:

var arrayPaths = new List<int[,]>(); 
arrayPaths.Add(new[,] { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }); // Include: starts with (0, 0) 
arrayPaths.Add(new[,] { { 0, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }); // Include: starts with (0, 1) 
arrayPaths.Add(new[,] { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }); // Exclude: starts with (1, 0) 
arrayPaths.Add(new int[0,0]);          // Exclude: has no data 

następnie podzbiór ścieżek, które rozpoczynają się w punkcie (0, 0) i (0, 1) to:

arrayPaths.Where(p => 
    p.GetUpperBound(0) >= 0 && 
    p.GetUpperBound(1) >= 1 && 
    (
     (p[0, 0] == 0 && p[0, 1] == 0) || 
     (p[0, 0] == 0 && p[0, 1] == 1) 
    )); 

Neville Nazerane miał dobrą sugestię w swoim komentarzu: użycie struktury danych innej niż tablica liczb całkowitych do przedstawienia punktu powinno dać kod, który jest znacznie łatwiejszy do zrozumienia.Na przykład, załóżmy, że definiowanie współrzędnych tak:

public struct Coordinate 
{ 
    public Coordinate(int x, int y) 
    { 
     X = x; 
     Y = y; 
    } 

    public int X { get; } 
    public int Y { get; } 

    public bool Equals(int x, int y) => 
     X == x && Y == y; 
} 

Następnie można zdefiniować zestaw ścieżek wyżej podane tak:

var objectPaths = new List<List<Coordinate>>(); 
objectPaths.Add(new List<Coordinate> { new Coordinate(0, 0), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) }); 
objectPaths.Add(new List<Coordinate> { new Coordinate(0, 1), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) }); 
objectPaths.Add(new List<Coordinate> { new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) }); 
objectPaths.Add(new List<Coordinate>()); 

a teraz podzbiór ścieżek jesteś zainteresowany jest :

objectPaths.Where(p => p.Count > 0 && (p[0].Equals(0, 0) || p[0].Equals(0, 1))); 

Jeśli chcesz bardziej zwięzłej składni dla określenia ścieżki w kodzie, wtedy można rozważyć bardzo prostą klasę reprezentuje ścieżkę. Na przykład:

public class Path : List<Coordinate> 
{ 
    public Path() { } 

    public Path(params (int x, int y)[] coordinates) => 
     AddRange(coordinates.Select(c => new Coordinate(c.x, c.y))); 
} 

Teraz można zdefiniować zbiór ścieżek jak:

var paths = new List<Path>(); 
paths.Add(new Path((0, 0), (0, 1), (1, 1), (2, 1))); 
paths.Add(new Path((0, 1), (0, 1), (1, 1), (2, 1))); 
paths.Add(new Path((1, 0), (0, 1), (1, 1), (2, 1))); 
paths.Add(new Path()); 

a składnię wybranie podzbioru chciałeś jest taka sama jak poprzednio.