2015-04-30 1 views
7

Ho la seguente classeLINQ distinta con i conteggi corrispondenti sulla base di una proprietà List

public class Photo 
{ 
    public int Id { get; set; } 
    public string Caption { get; set; } 
    public Collection<string> Tags { get; set; } 
} 

Una foto può avere più tag ad esso associati, e lo stesso tag può essere utilizzato in qualsiasi numero di foto diverse.

Quello che alla fine voglio fare è recuperare un elenco di tag distinti, con un conteggio del numero di foto assegnate a ciascun tag.

Non ho alcun controllo sui dati sottostanti: sto utilizzando un'API che ha un metodo di ricerca che sto utilizzando per recuperare una raccolta di foto, ma non esiste un metodo per ottenere un elenco di tag distinti.

Quindi la mia domanda è, se ho una vasta collezione di foto, come posso usare LINQ per ottenere un elenco distinto dei tag contenuti in questo elenco e ottenere il conteggio (di foto) per ciascuno di questi tag?

+0

Non sei sicuro di quello che stai chiedendo ... Che cosa hai provato? –

+0

Hmm prova 'Elenco . Dove (y = Lista . Seleziona (x = x.Tag) .Distinct() .Conti (y.Tag))). Count()' – Pseudonym

risposta

8
var tagCounts = photos 
    .SelectMany(photo => photo.Tags) 
    .GroupBy(tag => tag, (tag, group) => new { tag, count = group.Count() }) 
    .ToDictionary(tuple => tuple.tag, tuple => tuple.count); 

Il ragionamento è il seguente.

  • Ottenere la sequenza di tutti i tag, con ripetizione se più foto hanno lo stesso tag.
  • Raggruppa i tag ripetuti in base al loro valore e conta il numero di tag in ciascun gruppo.
  • Costruisce un mapping dizionario da ciascun tag al numero di foto che hanno quel tag.
+1

Abbastanza elegante, buon lavoro. –

+0

Molto bello, grazie :) – marcusstarnes

0

È possibile farlo in due passaggi.

  • First ottenere tag distinti dalla lista
  • Scorrere tag distinti e ottenere contare dall'elenco e metterlo in un Dictionary<string,int>

Qualcosa di simile:

List<Photo> list = new List<Photo>(); 
var distinctTags = list.SelectMany(r => r.Tags).Distinct(); 
Dictionary<string, int> dictionary = new Dictionary<string, int>(); 
foreach (string tag in distinctTags) 
{ 
    dictionary.Add(tag, list.Count(r=> r.Tags.Contains(tag))); 
} 
+0

Non mostra come ottenere un conteggio , come la domanda posta il conteggio – Pseudonym

+0

per ogni tag? che dovrebbe farlo 'dictionary.Add (tag, list.Count (r => r.Tags.Contains (tag)));' – Habib

+1

Non posso leggere oggi apparentemente, mi dispiace – Pseudonym

2

È possibile utilizzare SelectMany & GroupBy in questo modo: -

var result = photos.SelectMany(x => x.Tags, (photosObj, tags) => new {photosObj, tags}) 
        .GroupBy(x => x.tags) 
        .Select(x => new 
         { 
          Tags = x.Key, 
          PhotoId = String.Join(",",x.Select(z => z.photosObj.Id)) 
         }); 

questo vi darà tutti i tag e le rispettive PhotoIds al comma formato separato.

Aggiornamento:

Siamo spiacenti, solo noticied si desidera che il conte di Photos oggetto, in questo caso semplicemente bisogno di questo: -

var result = photos.SelectMany(x => x.Tags) 
        .GroupBy(x => x) 
        .Select(x => new 
           { 
            Tags = x.Key, 
            PhotoCount = x.Count() 
           }); 

Quindi, Supponiamo di avere questi dati: -

List<Photo> photos = new List<Photo> 
{ 
    new Photo { Id =1, Caption = "C1", Tags = new List<string> { "T1", "T2", "T3" }}, 
    new Photo { Id =2, Caption = "C2", Tags = new List<string> { "T4", "T2", "T5" }}, 
    new Photo { Id =3, Caption = "C3", Tags = new List<string> { "T5", "T3", "T2" }} 
}; 

avrete seguito di uscita: -

enter image description here

0
var list=new[]{ 
    new {id=1,Tags=new List<string>{"a","b","c"}}, 
    new {id=2,Tags=new List<string>{"b","c","d"}}, 
    new {id=3,Tags=new List<string>{"c","d","e"}}, 
}; 
var result=list.SelectMany(r=>r.Tags) 
    .GroupBy(r=>r,r=>r,(Key,Vals)=>new {Tag=Key,Count=Vals.Count()}); 

Risultato:

Tag Count 
a 1 
b 2 
c 3 
d 2 
e 1