2016-06-15 8 views
0

sagen, dass ich mit bestimmten Namen eine Liste der Zeichenfolge haben:Wie neu gruppieren, was unter einer Schwelle mit Linq ist?

APP_application1.exe 
APP_application2.exe 
APP_application3.exe 
APP_application4.exe 
CMD_Batch.exe 
PWS_Script.exe 
PWS_Script2.exe 
PWS_Script3.exe 
VBS_Script.exe 
VBS_Script2.exe 
[...] 

Ich möchte zusammen diejenigen mit dem gleichen Präfix neu zu formieren, aber nur, wenn sie über eine Schwelle sind. Diejenigen unter dieser Grenze sind in einem "anderen" -Tag zusammengefasst. Ich möchte auch maximal 5 Gruppen.

Group APP : {APP_application1.exe,APP_application2.exe,APP_application3.exe,APP_application4.exe} 
Group PWS : {PWS_Script.exe,PWS_Script2.exe,PWS_Script3.exe} 
Group other : {CMD_Batch.exe,VBS_Script.exe,VBS_Script2.exe} 

Gerade jetzt, ich habe meine Gruppen fest einprogrammiert, so kann ich mit einem Präfix filtern

filtered = _ 
    (From cell In listFiles _ 
     Where cell.ToUpper().StartsWith(prefix) 
     Select New SelectListItem() With { _ 
      .Text = cell, _ 
      .Value = cell _ 
     }).ToList() 

oder einen Filter mit denen außerhalb:

filtered = _ 
    (From cell In listFiles _ 
     Let prefix = cell.Substring(0, 3).ToUpper() 
     Where Not LIST_CODE.Contains(prefix) 
     Select New SelectListItem() With { _ 
      .Text = cell, _ 
      .Value = cell _ 
     }).ToList() 

Wo LISTE_CODE = {"APP","PWS"}
Ich möchte um LISTE_CODE loszuwerden und etwas wie MIN_GROUP_SIZE = 3 und MAX_GROUP = 5 zu verwenden, um mo zu sein re dynamisch.

Im Moment habe ich

Dim grp = 
    (From cell In listFiles _ 
    Let prefixe = cell.Substring(0.3).ToUpper() 
    Group By pre = prefixe Into g = Group 
    Where g.Count() < MIN_GROUP_SIZE 
    Select g) 

Aber es funktioniert nicht bei allen Gruppe.

Habe ich den richtigen Ansatz?
Was ist los mit meinem group by?

Antwort

1

Ich würde in kleineren Schritten fortfahren. (Fehlerbehandlung ist nicht enthalten.)

var names = new string[] { 
    "APP_application1.exe", 
    "APP_application2.exe", 
    "APP_application3.exe", 
    "APP_application4.exe", 
    "CMD_Batch.exe", 
    "PWS_Script.exe", 
    "PWS_Script2.exe", 
    "PWS_Script3.exe", 
    "VBS_Script.exe", 
    "VBS_Script2.exe" 
}; 

var MIN_GROUP_SIZE = 2; 
var MAX_GROUP = 2; 

// Helper to extract the uppercase prefix 
Func<string, string> GetPrefix = (name) => name.Split('_')[0].ToUpper(); 

var groupsForPrefixes = names.GroupBy(name => GetPrefix(name)); 
// Collect the prefixes for the first MAX_GROUP groups that have at least MIN_GROUP_SIZE items 
var prefixes = groupsForPrefixes.Where(grp => grp.Count() >= MIN_GROUP_SIZE).Take(MAX_GROUP).Select(grp => grp.Key); 

var groupsOfNames = names.GroupBy(name => prefixes.Contains(GetPrefix(name)) ? GetPrefix(name) : "OTHER"); 

Das Ergebnis in LINQPad

IEnumerable<IGrouping<String,String>> (3 items) 

Key= APP 

IGrouping<String,String> (4 items) 
    App_application1.exe 
    APP_application2.exe 
    APP_application3.exe 
    APP_application4.exe 

Key= OTHER 

IGrouping<String,String> (3 items) 
    CMD_Batch.exe 
    VBS_Script.exe 
    VBS_Script2.exe 

Key= PWS 

IGrouping<String,String> (3 items) 
    PWS_Script.exe 
    PWS_Script2.exe 
    PWS_Script3.exe 

Vergib mir meine mit C# statt VB; Ich hoffe es hilft trotzdem.

Hier ist es jetzt in VB (konvertiert mit dem Telerik Code Converter Service).

Dim names = New String() { 
    "APP_application1.exe", 
    "APP_application2.exe", 
    "APP_application3.exe", 
    "APP_application4.exe", 
    "CMD_Batch.exe", 
    "PWS_Script.exe", 
    "PWS_Script2.exe", 
    "PWS_Script3.exe", 
    "VBS_Script.exe", 
    "VBS_Script2.exe"} 

    Dim MIN_GROUP_SIZE = 2 
    Dim MAX_GROUP = 2 

    ' Helper to extract the uppercase prefix 
    Dim GetPrefix As Func(Of String, String) = Function(name) name.Split("_"c)(0).ToUpper() 

    Dim groupsForPrefixes = names.GroupBy(Function(name) GetPrefix(name)) 
    ' Collect the prefixes for the first MAX_GROUP groups that have at least MIN_GROUP_SIZE items 
    Dim prefixes = groupsForPrefixes.Where(Function(grp) grp.Count() >= MIN_GROUP_SIZE).Take(MAX_GROUP).[Select](Function(grp) grp.Key) 

    Dim groupsOfNames = names.GroupBy(Function(name) If(prefixes.Contains(GetPrefix(name)), GetPrefix(name), "OTHER")) 
1

Hier ist eine Möglichkeit, wie Sie Ihr Ziel erreichen können.

Die Verwendung von Lookups ist eine großartige Möglichkeit, Ihre Ergebnismengen zu partitionieren. Sie können dies zu Ihrem Vorteil nutzen, um zu bestimmen, was innerhalb des Schwellenwerts liegt, und diejenigen, die nicht innerhalb des Schwellenwerts liegen, neu zu kombinieren.

Dim threshold = 3 
Dim grouped = 
    From name In names 
    Let prefix = name.Split("_"c).First.ToUpper 
    Group name By prefix Into Group, Count 
Dim partition = grouped.ToLookup(
    Function(x) x.Count >= threshold, 
    Function(x) New With { x.Group, x.prefix } 
) 
Dim query = partition(True).Concat(
    From x In partition(False) 
    From name In x.Group 
    Group name By prefix = "OTHER" Into Group 
    Select New With { Group, prefix }).ToList 
0

Ich landete es in 2 Teilen zu tun:

 Dim listGroup = From listeCmd In listFiles 
        Let prefixe = listeCmd.Substring(0, 3).ToUpper() 
        Group By prefix Into Group 
        Order By Group.Count() Descending 

     listeB = listeGroup.Where(Function(e) e.Group.Count >= MIN_ITEM_PR_PREFIX) _ 
           .Take(MAX_GROUPE) _ 
           .Select(Function(e) e.prefix).ToList() 

Das hat mir meine Liste der Namen der Gruppe, die ich verwendet, um meine LIST_CODE const zu ersetzen.

Dies ist ziemlich ähnlich zu Attila Karoly Antwort.