Giusto, provo a postare le mie 2 versioni di Generics Extension, che si possono applicare a tutte le matrici bidimensionali.
La sostanza principale era quella di dotare la funzione di un funzionale di filtro (il tuo Func<int,bool>) da poter applciare dinamicamente, e che puo' essere risolto dall'utilizzatore mediante una comodissima lambda function.
Per matrice bidimensionale ho inteso proprio la matrice C# con la sintassi [y,x] e non quella tipica del C e C++ come la [y][x]
Ovvio che si possono portare anche per la versione piu' vecchia.
La prima versione e' iterativa, la seconda e' funzionale.
Per questo caso penso che avrei scelto la iterativa.
Codice:
public static T[,] GetFiltered<T>(this T[,] domain, Func<T, bool> pass)
{
int dy = domain.GetLength(0); //0 e 1 sono le dimensioni.
int dx = domain.GetLength(1);
T[,] ret = new T[dy, dx];
for (int y = 0; y < dy; y++)
{
for (int x = 0; x < dx; x++)
{
T test = domain[y,x];
ret[y, x] = pass(test) ? test : default(T);
}
}
return ret;
}
public static T[,] GetFiltered2<T>(this T[,] domain, Func<T, bool> pass)
{
int dy = domain.GetLength(0);
int dx = domain.GetLength(1);
T[,] ret = new T[dy, dx];
var universe = from y in Enumerable.Range(0, dy)
from x in Enumerable.Range(0, dx)
let test = domain[y, x]
let res = pass(test) ? test : default(T)
select new {y=y,x=x,res=res};
universe.ForEach(an => ret[an.y, an.x] = an.res);
return ret;
}
public static void ForEach<T>(this IEnumerable<T> domain, Action<T> action)
{
foreach (T t in domain) action(t);
}
E l'uso che se ne puo' fare e' p.es.:
Codice:
static void Main(string[] args)
{
int[,] Mat1 = { { 1, 2, 3 }, { 4, 5, 6 } };
int[,] Mat1Filt = Mat1.GetFiltered(t => t > 4);
double[,] Mat2 = { { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 } };
double[,] Mat2Filt = Mat2.GetFiltered2(u => u > 4.5);
}
Tutto fortemente tipizzato e lamentato a compile time se qualche tipo esce fuori dai ranghi.
Ora, sto cercando di capire se e' possibile avere davvero un enumeratore doppio. Intendo, un'enumerazione che abbia alla fine non un sola dimensione ma piu' di una.
L'enumerazione di cui sopra restituisce una serie di oggetti. Ogni oggetto contiene le 2 coordinate (e il risultato del filtro), e su questo ho giocato.
Mi sarebbe invece piaciuto ottenere un'enumerazione doppia, con 2 parametri interi (u,v) invece che uno solo tipizzato (t)
E' una questione di lana caprina, ma mi sarebbe piacuto scrivere qualcosa come la prima, invece che la seconda.
Codice:
universe.ForEach((t, u) => ret[t, u] = qualcosa);
universe.ForEach(an => ret[an.y, an.x] = qualocosa);