Find in the list all arrays whose first element matches those that match the condition

This is a question that is very difficult to name.

In C #, I have a set of int[,] arrays stored in List<int[,]> paths , each of which contains a set of coordinates for forming the path. Example: { {0,0}, {0,1}, {1,1}, {2,1} } .

Now I want to save in paths all paths that have the same first index as one of the first indices of all paths matching the condition.

To better demonstrate what I mean, let's say I get all the paths with an odd length:

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

Say this returns a list containing some arrays whose first coordinates are {0,0} or {0,1}, for example. I want paths to be paths.Where( x=> x first chords were either {0,0} or {0,1} ) . How can I achieve this?

Hope that I mean, understand.

+5
source share
3 answers

If you use your current data structure, you can do this, but the syntax will not be good. Basically, this is similar to what A. Milto suggested in his answer, except that you need a border check to rule out an exception in case of an empty path. Therefore, if you define your paths as follows:

 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 

Then the subset of paths starting with (0, 0) or (0, 1) is equal 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 Nazeran had a good suggestion in his comment: using a data structure other than an array of integers to represent a point should lead to a much more understandable code. For example, suppose you define a coordinate like this:

 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; } 

You can then define the set of paths above as follows:

 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>()); 

And now a subset of the paths you are interested in:

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

If you need a more concise syntax for specifying paths in your code, you can consider a very simple class to represent the path. For instance:

 public class Path : List<Coordinate> { public Path() { } public Path(params (int x, int y)[] coordinates) => AddRange(coordinates.Select(c => new Coordinate(cx, cy))); } 

Now you can define a set of paths as:

 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()); 

And the syntax for choosing the right subset is the same as before.

+1
source

Like this:

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

Or, if you prefer to continue to work with the same type of collection:

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

Here is one for this, assuming the List below represents your multidimensional elements:

 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 } } }; 

define ie criteria:

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

define an extension method that should allow us to crop a multidimensional array only for the first coordinates, just for filtering.

 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]; } } } 

then you can do:

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

resultSet will now contain two multidimensional arrays that meet the specified criteria ie:

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

Source: https://habr.com/ru/post/1273451/


All Articles