2009-05-05 12 views
6

Ho una lista <> di una classe "region" con due variabili, "startLocation" e "endLocation". Mi piacerebbe combinare questi due in un nuovo ordinamento 2 array ordinati dove la sua giusta posizione e un intero che rappresenta se il suo inizio o una fine.C# - Usando LINQ per prendere due variabili in un array bidimensionale?

Ad esempio, se la lista ha tre oggetti regione con

[Regione 1]: StartLocation = 5, endLocation = 7

[Regione 2]: StartLocation = 3, endLocation = 5

[Regione 3]: StartLocation = 8, endLocation = 9

mi piacerebbe ottenere un ordinato matrice bidimensionale (o una lista o simile) che sembra:

[3] [1]

[5] [1]

[5] [-1]

[7] [-1]

[8] [1]

[9] [-1]

(preferibilmente vorrei le sovrapposizioni per aggiungere i secondi valori di insieme, in modo che i due distinti 5 di dell'array sarebbero combinati in [5 0] ... ma non è troppo importante)

I Attualmente sto utilizzando un forloop regolare che passa attraverso uno per uno e li aggiungo a un elenco uno alla volta. Questa implementazione è piuttosto lenta perché sto lavorando con dataset di grandi dimensioni e suppongo che ci sia un modo più elegante/più veloce per raggiungere questo obiettivo tramite LINQ.

Qualsiasi suggerimento sarebbe molto apprezzato.

risposta

5

Avrai bisogno di definire un metodo di supporto che si divide una regione in 2 parti ed è molto più facile per rappresentare questo utilizzando una nuova vs. struct un array 2D

struct Data { 
    public int Value; 
    public bool IsStart; 
} 

public static IEnumerable<Data> Split(this Region region) { 
    yield return new Data() { Value = region.StartLocation, IsStart=true}; 
    yield return new Data() { Value = region.EndLocation, IsStart=false}; 
} 

Quindi è possibile utilizzare la seguente query LINQ per suddividerli e ordinarli.

List<Region> list = GetTheList(); 
var query = list 
    .SelectMany(x => x.Split()) 
    .OrderBy(x => x.Data); 
+0

sembra una buona idea. lasciami fare un tentativo e vedere se è più veloce di quello che ho ora. Grazie! – DarkAmgine

+1

Perché non è questo .SelectMany (x => x.Split())? – mquander

+0

Questo approccio produce (nessun gioco di parole!) Nessun vantaggio su un foreach, e in effetti introduce ulteriori overhead con i numerosi enumeratori utilizzati qui. È decisamente intelligente, ma non lo vedo più veloce o più leggibile. –

0

Questa non è una soluzione adatta per LINQ in altro che un esercizio intellettuale. Un ciclo foreach sarà altrettanto veloce (in realtà probabilmente più veloce) rispetto a qualsiasi implementazione LINQ accartocciata.

Come nota a margine, presumo che si stia utilizzando foreach anziché for. In caso contrario, è possibile accelerare significativamente il processo passando al ciclo foreach.

foreach(Region r in regionList) 
{ 
    // add your entries using r 
} 

sarà molto più veloce di ..

for(int i = 0; i < regionList.Count; i++) 
{ 
    // add your entires using the indexer 
} 
+0

Qualcuno può indicarmi la fonte su questo foreach/per differenza di prestazioni? L'ho visto citato come Gospel in diversi posti senza fonte per uno scenario di test che posso eseguire. Ogni test che ho eseguito ha questi due modi collo e collo, uno leggermente più veloce con una lista, uno leggermente più veloce con un array, ma tutti gli altri sembrano essere dell'opinione che uno sia drasticamente più veloce dell'altro (sebbene sia sembra variare). –

+0

foreach è più veloce per le raccolte di dimensioni dinamiche come Elenco perché l'indicizzatore di un elenco non punta a uno slot di memoria relativo come quello di un array. L'indicizzatore su una matrice è più veloce perché non ha il (leggero) sovraccarico della creazione di un enumeratore e il controllo dei limiti ad ogni iterazione. Nel suo scenario sta usando una lista , quindi sì, un foreach sarebbe più veloce. –

Problemi correlati