2013-08-02 15 views
6

Podana jest poniższa tablica (każdy blok [], oznacza wpis):podziału gromadzenia się obiektu w zależności od stanu i występowania

[A=1] [A=5] [S=3] [A=7] [C=3] [T=2] [F=9] [Z=4] [N] [C=3] [E=8] 
[A=7] [N] [Z=6] [Q=1] [P=2] [Y=7] [S=3] [N] 

trzeba podzielić go do obiektów typu „N” (NObject) gdzie jak każdy inny znak reprezentuje określoną właściwość tego obiektu NObject do następnego wystąpienia "N". Do pierwszego wystąpienia "N" znaki należą do innego obiektu (nazwijmy to PObject). Więc zadania powinny spełniać follwing:

  1. mapie każdy znak do nieruchomości PObject
  2. Po pierwsze occurrs „n”, utwórz nowy NObject
  3. mapie każdy znak do właściwości tego NObject
  4. Jeśli wystąpi kolejna postać N utwórz nowy NObject

Obecnie w Pseudokod moje rozwiązanie wygląda następująco co uważam jest dalekie od ideału.

PObject pobject = new PObject(); 
NObject nobject; 

CollectionOfKeyValuePairs collection = MyArray.Split('=').MapKeysValues() 

foreach(entry in collection) { 
    switch(entry.Key): 
     case A: 
      (nobject ?? (CommonBase) pobject).A += entry.Value; break; 
     case B: 
      (nobject ?? (CommonBase) pobject).B += entry.Value; break; 
     case C: 
      (nobject ?? (CommonBase) pobject).C += entry.Value; break; 
     case E: 
      pobject.E += entry.Value; break; 
     case F: 
      (nobject ?? (CommonBase) pobject).F += entry.Value; break; 
     case G: 
      (nobject ?? (CommonBase) pobject).G += entry.Value; break; 
     case H: 
      (nobject ?? (CommonBase) pobject).H += entry.Value; break; 
     ... 
     ... 
     ... 
     case N: 
      nobject = new NObject(); 
     .... 
     .... 
    } 
} 

Który daje mi dokładnie to, co chcę:

[pobject] 
A = 23 
B = 63 
C = 23 
... 

[nobject] 
A = 34 
B = 82 
C = 12 
... 

[nobject] 
H = 236 
K = 2 
... 

[nobject] 
// N occurred in array, but no properties followed 

Ale z ponad 30 możliwych identyfikatorów własności (co oznacza 30 warunki switch) oraz własności przypisany wyłącznie na podstawie faktu, że nobject może być null (i tworzenie nowego każdego wystąpienia "N" char): Kod jest niesamowicie śmierdzący. Ale nie wiem, jak to zrobić inaczej, może z wbudowanymi funkcjami kolekcji, LINQ lub czymkolwiek innym.

+0

Odbicie usunęłoby komunikat z przełącznika, ale nie jestem pewien, czy przeczytałem twoje pytanie na tyle dobrze, aby zrozumieć, że jest ci przykro. – Sayse

+0

Możesz użyć biblioteki gravell [FastMember] (https://code.google.com/p/fast-member/), aby uzyskać dostęp do elementów obiektu według ich nazwy ("A", "B", ...) – xanatos

+0

Czy celowe jest dodawanie do właściwości zamiast ich ustawiania? (nobject ?? (CommonBase) pobject) .H + = entry.Value; zamiast (nobject ?? (CommonBase) pobject) .H = entry.Value; – ne2dmar

Odpowiedz

1

Możesz używać Słownika do przechowywania par klucz-wartość zamiast jawnie tworzyć właściwości dla każdego możliwego przypadku. Coś jak:

List<Dictionary<char,int>> listOfPNObjects = new List<Dictionary<char,int>>(); 
listOfPNObjects.Add(new Dictionary<char,int>()) //create default P dictionary 
foreach(entry in collection) { 
    if(entry.Key == N) 
    { 
      listOfPNObjects.Add(new Dictionary<char,int>()); 
    } 
    else 
    { 
      listOfPNObjects[listOfPNObjects.Count - 1].Add(entry.key, entry.value); 
    } 

} 
+0

Niestety, potrzebuję tych właściwości, ponieważ mam do nich bezpośredni dostęp. :( – user2644817

+0

następnie można zrobić getters własności, aby uzyskać dostęp do słownika – ne2dmar

+0

Oh, rozumiem.Oto, w tym przypadku mój przykład został wybrany trochę pecha.Zapraszam tam liczb całkowitych dla łatwiejszego zrozumienia, w moim rozwiązaniu, są to liczby całkowite, ciągi i inne obiekty, które w niektórych przypadkach muszę sparsować dalej. :) – user2644817

1

mam przepisany kod za pomocą refleksji i LINQ:

var objects = keyValuePairList 
    .Aggregate<KeyValuePair<string, dynamic>, List<CommonBase>>(
     new List<CommonBase>(), (a, p) => 
      { 
       CommonBase cObject; 
       if (p.Key == "N") 
       { 
        cObject = new NObject(); 
        a.Add(cObject); 
       } 
       if (a.Count == 0) 
       { 
        cObject = new PObject(); 
        Process(p, ref cObject); 
        a.Add(cObject); 
       } 
       else 
       { 
        cObject = a.Last(); 
        Process(p, ref cObject); 
       } 
       return a; 
      }); 

Wewnątrz metody Process gdzie można obsługiwać przetwarzanie właściwości, na podstawie ich typu:

private static void Process(
     KeyValuePair<string, dynamic> kvPair, 
     ref CommonBase cObject) 
{ 
    var propertyInfo = typeof(CommonBase).GetProperty(kvPair.Key); 
    switch (propertyInfo.PropertyType.FullName) 
    { 
     case "System.Int32": 
      propertyInfo 
       .SetValue(cObject, 
        (int)propertyInfo.GetValue(cObject) + (int)kvPair.Value); 
      break; 
    } 
} 
Powiązane problemy