Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine porta Logan in un'avventura inedita, violenta e fortemente narrativa, costruita attorno alla sua natura di combattente e al difficile rapporto con il proprio passato. Insomniac Games punta su combattimenti spettacolari, progressione e personalizzazione, inserendo l'azione in un mondo segnato dalla persecuzione dei mutanti. Un viaggio intenso, che alterna mattanza, esplorazione e momenti sorprendentemente emotivi.
DJI Romo 2: tante novità lo rendono un robot completo
DJI Romo 2: tante novità lo rendono un robot completo
Romo 2 è la seconda generazione di robot lavapavimenti di DJI, un modello che si caratterizza per la precisione nel sistema di navigazione e per il funzionamento particolarmente silenzioso. Con le modifiche introdotte in questa seconda versione, e un posizionamento di prezzo più allineato alla concorrenza, rappresenta una valida alternativa sul mercato delle soluzioni di pulizia domestica
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED
Il primo Sony con retroilluminazione True RGB alla prova del banco di misura e dei contenuti: luminanza enorme, colori accurati in HDR e un antiriflesso molto efficace. I limiti sono due sole HDMI 2.1 e il blooming fuori asse
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 16-07-2008, 20:53   #1
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12113
[LINQ] analisi di matrici

Finora con linq ho lavorato prettamente con dati sequenziali, ma come dovrebbe funzionare in caso di matrici n-dimensionali?
E' possibile utilizzarlo efficacemente o è limitato solo a collection uni-dimensionali?
Ho fatto una rapida prova con una matrice di interi con questo codice:
Codice:
int[][] matrix = {
                             new int[]{1,2,3},
                             new int[]{4,5,6},
                             new int[]{7,8,9}};

            var result = matrix.Select(row => row.Where(value => value > 5));
            foreach (var r in result) r.ForEach(Console.WriteLine);
Che da il risultato voluto, ovvero restituisce i numeri 6, 7, 8 e 9, però ho dovuto usare una Select sulla matrice.
Così facendo in pratica ho ricevuto 3 oggetti Enumerable, mentre ad esempio del primo non saprei che farmene dato che non contiene nessun oggetto maggiore di 5.
Avevo provato inizialmente ad usare un altro Where al posto del Select ma non buildava...
Quale sarebbe quindi la soluzione migliore (se esiste) per lavorare su dati di tipo matriciale con Linq?
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 07:13   #2
cdimauro
Senior Member
 
L'Avatar di cdimauro
 
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
A naso sembra che lavori sempre con dati sequenziali, come anche il tuo esempio dimostra.

Non mi sembra un limite. Tra l'altro finora non m'è mai capitato di lavorare con matrici (omogenee) multidimensionali.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro
@LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro
Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys
cdimauro è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 08:33   #3
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Si', lavora su elementi monodimensionali, ma a tutto c'e' una soluzione.
Ti passo qui 3 modi di risolvere il problema, con l'extension a corredo
Il primo e' piu' simile al tuo, ma con la SelectMany eviti di dover usare un terzo enumeratore.
In pratica la SelectMany e' la UNION ALL dell'SQL, che unisce insieme gli elementi di una sottoenumerazione.

Il secondo fa uso di una Matrice Multidimensionale, con a corredo un AsEnumerable per poter ciclare sugli elementi.
Dovrebbe essere la soluzione migliore per le matrici in C#, dato che rango della matrice e lunghezza di ciascuna dimensione sono fissi e il compilatore lo sa a compile-time.

Il terzo e' di nuovo simile al primo, ma usa una doppia enumerazione creata al volo per accedere ai singoli elementi.
Ovviamente non funziona se la matrice e' atipica (con lunghezza di righe diversa)
In pratica mette in prodotto cartesiano le due enumerazioni, costruendo quindi ogni coppia possibile di X e Y.
Sembra essere la soluzione preferita in caso di computo di grosse moli di lavoro per ciascun elemento, dato che puo' essere resa parallelizzabile semplicemente se al posto della prima Enumerable usi una ParallelEnumerable. Ma non ho fatto studi di fattibilita' in tal senso sugli altri esempi.

Codice:
static class Program
{
    static void Main(string[] args)
    {
        int[][] matrix = {
                         new int[]{1,2,3},
                         new int[]{4,5,6},
                         new int[]{7,8,9}};

        var result = matrix.SelectMany(row => row.Where(value => value > 5));

        result.ForEach(Console.WriteLine);

        Console.ReadKey();
    }


    static void Main2(string[] args)
    {
        int[,] matrix = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

        var result = matrix.AsEnumerable().Where(t => t > 5);
        result.ForEach(Console.WriteLine);

        Console.ReadKey();
    }

    static void Main3(string[] args)
    {
        int[][] matrix = {
                         new int[]{1,2,3},
                         new int[]{4,5,6},
                         new int[]{7,8,9}};

        int rank = matrix.Rank;
        int dim1 = matrix.Length;
        int dim2 = matrix[0].Length;

        var result = from y in Enumerable.Range(0, dim1)
                     from x in Enumerable.Range(0, dim2)
                     let val= matrix[y][x]
                     where val>5
                     select val;


        result.ForEach(Console.WriteLine);

        Console.ReadKey();
    }

    static IEnumerable<T> AsEnumerable<T>(this T[,] domain)
    {
        foreach (T elem in domain)
            yield return elem;
    }

    static void ForEach<T>(this IEnumerable<T> domain, Action<T> action)
    {
        foreach (T t in domain) action(t);
    }
}
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto.
E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 09:41   #4
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Piu' interessante potrebbe essere costruire un metodo tipo:

Data una matrice bidimensionale, restituire una matrice bidimensionale di pari geometria, ma con valorizzate solo le celle che soddisfano un determinato filtro.

Es: elemento>5

Con anche il filtro passato come parametro, diverso di volta in volta.
Ho provato, possono venire fuori cose interessanti.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto.
E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 13:24   #5
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12113
Il metodo + interessante mi sembra così ad occhio il secondo.
Nel terzo metodo ho scoperto le doppie enumerazioni che ancora non avevo mai visto
ora vedo se riesco a restituire la matrice originale con valorizzati i parametri che soddisfano la condizione espressa nel filtro
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 14:02   #6
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12113
l'implementazione + semplice che mi è venuta in mente è questa:
Codice:
class Program
    {
        static void Main(string[] args)
        {
            int[][] matrix = {
                             new int[]{1,2,3},
                             new int[]{4,5,6},
                             new int[]{7,8,9}};

            var result = matrix.Select(row => row.Select(value => value > 5 ? value : 0));
            
            foreach (var row in result) 
            {
                foreach (var value in row)
                {
                    Console.Write(value);
                }
                Console.WriteLine();
            }

            Console.ReadLine();
        }
ce ne sono di migliori che mi sono sfuggite?
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 14:05   #7
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Il requisito che avevo in mente era una funzione che, dato in ingresso una matrice tipo int [][]
restituisse di nuovo un oggetto matrice, con la stessa geometria, applicando il filtro agli elementi.

Intendo una matrice vera, non solo a video
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto.
E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 14:13   #8
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12113
Quote:
Originariamente inviato da gugoXX Guarda i messaggi
Il requisito che avevo in mente era una funzione che, dato in ingresso una matrice tipo int [][]
restituisse di nuovo un oggetto matrice, con la stessa geometria, applicando il filtro agli elementi.

Intendo una matrice vera, non solo a video
ah ok
ora non ho tempo che ho chiuso parallels e devo scappare al lavoro
gli do un occhiatina stasera
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 17-07-2008, 23:16   #9
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12113
non riesco a fare andare il predicate
Codice:
class Program
    {

        static void Main(string[] args)
        {
            int[][] matrix = {
                             new int[]{1,2,3},
                             new int[]{4,5,6},
                             new int[]{7,8,9}};

            int[][] result = matrix.Filter(value => value > 5);   
            
            foreach (int[] row in result) {
                foreach (int value in row)
                {
                    Console.Write(value);
                }
                Console.WriteLine();
            }

            Console.ReadLine();
        }
    }
mi da errore nella riga in bold dicendo:
"Error 1 The type arguments for method 'ProvaLinq.Extensions.Filter<TSource>(int[][], System.Func<int,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. C:\Visual Studio 2008\Projects\ProvaLinq\ProvaLinq\Program.cs 18 30 ProvaLinq"
l'extension method è il seguente:
Codice:
public static int[][] Filter<TSource>(this int[][] matrix, Func<int, bool> predicate)
        {
            return matrix.Select(row => row.Select(value => predicate(value) ? value : 0).ToArray<int>()).ToArray<int[]>();
        }
Ovviamente senza predicate riesco a farla funzionare, ma ancora come utilizzare i delegates durante l'implementazione devo capirlo...
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 18-07-2008, 09:58   #10
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12113
ce l'ho fatta..
a mente libera ho risolto il problema
Codice:
public static int[][] Filter(this int[][] matrix, Func<int, bool> predicate)
        {
            return matrix.Select(row => row.Select(value => predicate(value) ? value : 0).ToArray<int>()).ToArray<int[]>();
        }
certo che però ancora non ho capito proprio tutto di queste funzioni implementate in questo modo...
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 18-07-2008, 10:38   #11
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
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);
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto.
E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test.

Ultima modifica di gugoXX : 18-07-2008 alle 10:46.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa Marvel's Wolverine, la recensione: Logan torna p...
DJI Romo 2: tante novità lo rendono un robot completo DJI Romo 2: tante novità lo rendono un ro...
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED Sony Bravia 9 II: il True RGB alla prova, dove l...
Geely EX5, un mese al volante: il SUV elettrico cinese che ci ha sorpreso (quasi) senza riserve Geely EX5, un mese al volante: il SUV elettrico ...
Mova Z70 Ultra Roller Complete: motore potente, rullo di lavaggio e l'IA a guidare Mova Z70 Ultra Roller Complete: motore potente, ...
Avio si prepara ai test del Dimostratore...
Space Pioneer ha annunciato le cause del...
Anthropic avrebbe nuovi antibiotici cont...
Scoperto un 'moltiplicatore nascosto' ne...
DREO: a IFA 2026 4 novità fra cui...
Slackbot genera dashboard e microsite de...
Idrogeno, nuova cella a combustibile rag...
Con la NASA fuori dai giochi, l'ESA risc...
Una falla di ChatGPT permette di estrapo...
Piano clima, 1,34 miliardi per il bonus ...
Porsche esce definitvamente da Bugatti R...
NVIDIA App aggiunge una delle funzioni p...
Come sarebbe il mondo se la luce viaggia...
Titanio, ceramica e zaffiro per HUAWEI W...
Taglio delle accise sul gasolio prorogat...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 00:53.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v