2016-08-16 3 views
0

Bei einer Sequenz zu entfernen: -Wie wie unten Duplikate in der Mitte

var list = new[] {"1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a"}.Select(x => new { P1 = x.Substring(0,1), P2 = x.Substring(1,1)}); 

Ich mag die Duplikate in der „Mitte“ mit, um am Ende entfernen: -

var expected = new[] {"1a", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a"}.Select(x => new { P1 = x.Substring(0, 1), P2 = x.Substring(1, 1) }); 

Also werden alle Wiederholungen von mehr als zwei ausgesondert. Es ist wichtig, dass ich das erste und letzte Duplikat bekomme.

+0

Sie 'GroupBy' verwenden können, da es um bewahrt (http://stackoverflow.com/questions/1452507/linq -to-objects-does-groupby-preserve-order-of-elements) oder 'Aggregate'. –

Antwort

1

Für diejenigen, die eine super kurze Antwort mit Schließung nicht hier Aggregat und wollen:

var data = new[] { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "1e", "5a", "6a", "7a", "7b", "8a" }; 
char priorKey = ' '; 
int currentIndex = 0; 

var result2 = data.GroupBy((x) => x[0] == priorKey ? new { k = x[0], g = currentIndex } : new { k = priorKey = x[0], g = ++currentIndex }) 
    .Select(i => new[] { i.First(), i.Last() }.Distinct()) 
    .SelectMany(i => i).ToArray(); 

Hat Tip für den Code @Slai dies auf basiert (Ich habe eine Lösung für die nicht-kontinuierlichen Gruppenausgabe.)


Hier ist, wie es mit Aggregat zu tun. Ich habe nicht alle Randfälle getestet ... nur Ihre Testfälle.

var list = new[] { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a" } 
      .Aggregate(new { result = new List<string>(), first = "", last = "" }, 
       (store, given) => 
       { 
       var result = store.result; 
       var first = store.first; 
       var last = store.last; 

       if (first == "") 
        // this is the first one. 
        first = given; 
       else 
       { 
        if (first[0] == given[0]) 
        last = given; 
        else 
        { 
        result.Add(first); 
        if (last != "") 
         result.Add(last); 
        first = given; 
        last = ""; 
        } 

       } 
       return new { result = result, first = first, last = last }; }, 
       (store) => { store.result.Add(store.first); if (store.last != "") store.result.Add(store.last); return store.result; }) 
      .Select(x => new { P1 = x.Substring(0,1), P2 = x.Substring(1,1)}); 

Ich erstelle ein Objekt, um die Liste so weit und die erste und letzte bis jetzt zu halten.

Dann verwende ich nur Logik, um die mittleren Sachen zu entfernen.

1

Gruppe nach dem ersten Zeichen und nehmen Sie die erste und letzte Element jeder Gruppe:

var list = "1a 1b 1c 1d 2a 3a 4a 4b 5a 6a 7a 7b 8a".Split(); 

var result = list.GroupBy(i => i[0]) 
    .Select(i => new[] { i.First(), i.Last() }.Distinct()) 
    .SelectMany(i => i).ToArray(); 

Debug.Print(string.Join("\", \"", result)); 
// { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a" } 
+0

Ihre Antwort ist prägnanter als Hogans, aber es erlaubt keine Wiederholung, z. var list = "1a 1b 1c 1d 2a 3a 4a 4b 1e 5a 6a 7a 7b 8a". Das heißt, ich habe Ihren Code in Kombination mit https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq/GroupAdjacent.cs verwendet, um mein Ziel zu erreichen. Danke für den Zeiger, ich dachte an GroupByUntil oder so. – user630190

+0

@ user630190 Ich denke, du meinst "nicht zusammenhängende Gruppen aufteilen", wenn du Wiederholung sagst. Das Beispiel, das Sie angegeben haben, muss sowohl 1a 1d als auch später 1e zurückgeben. – Hogan

+0

Yup, richtig. Mein Fehler, es nicht zu berücksichtigen. – user630190