2012-11-09 80 views
3

陣列不同的λ的比較我有以下形狀數據具有優先

someArray = [{ Name: "Some Class", TypeEnum: "Default" }, 
{ Name: "Some Class", TypeEnum: "Other" }, 
{ Name: "Some Class 2", TypeEnum: "Default" }, 
{ Name: "Some Class 2", TypeEnum: "Other" }, 
{ Name: "Some Class 3", TypeEnum: "Default" }, 
{ Name: "Some Class 4", TypeEnum: "Not Other" }] 

想象每個那些如C#對象

我需要的是該陣列的不同版本的陣列,優選給定一個選定的TypeEnum。例如,如果我選擇了其他的TypeEnum,我還是希望它默認爲默認值,如果它不能找到一個版本的類與「其他」 TypeEnum

例如隨着「其他」選擇爲ENUM類型,上面的數據會看起來像

[{ Name: "Some Class", TypeEnum: "Other" }, 
{ Name: "Some Class 2", TypeEnum: "Other" }, 
{ Name: "Some Class 3", TypeEnum: "Default" }] 

我現在正在做的是從here

TypeEnum myEnum = "Other" 
someArray.Distinct((x,y) => x.Name == y.Name && 
        x.TypeEnum != myEnum && 
        (y.TypeEnum == myEnum || y.TypeEnum == "Default")); 

我希望鮮明彈出一個lambda比較數組中的任何x都會從該表達式中得到一個true。

我錯了我認爲不同的作品。如果我是,我應該用什麼來代替?

回答

2

可以定義一個Comparer<T>類來處理自己的喜好進行比較,就像這樣:

public class SomeClassComparer : Comparer<SomeClass> 
{ 
    private TypeEnum _preference; 

    public SomeClassComparer(TypeEnum preference) 
     : base() 
    { 
     _preference = preference; 
    } 

    public override int Compare(SomeClass x, SomeClass y) 
    { 
     if (x.Name.Equals(y.Name)) 
     { 
      return x.TypeEnum == y.TypeEnum ? 0 
       : x.TypeEnum == _preference ? -1 
       : y.TypeEnum == _preference ? 1 
       : x.TypeEnum == TypeEnum.Default ? -1 
       : y.TypeEnum == TypeEnum.Default ? 1 
       : x.TypeEnum.CompareTo(y.TypeEnum); 
     } 
     else 
      return x.Name.CompareTo(y.Name); 
    } 
} 

UPDATE: 如果你只在您的首選或默認TypeEnum元素感興趣,你可以過濾掉其餘的首先。然後根據比較器對數組進行排序,即給予比默認更高的優先級TypeEnum。最後組他們的名字的對象,並採取從每個組的第一個:

var result = someArray.Where(x => x.TypeEnum == TypeEnum.Default || x.TypeEnum == myEnum) 
         .OrderBy(x => x, new SomeClassComparer(myEnum)) 
         .GroupBy(x => x.Name) 
         .Select(x => x.First()); 

或者你可以用下面的版本,如果你不希望定義一個比較器類:

Comparison<SomeClass> compareByTypeEnum = (x, y) => 
{ 
    if (x.Name.Equals(y.Name)) 
    { 
     return x.TypeEnum == y.TypeEnum ? 0 
      : x.TypeEnum == myEnum ? -1 
      : y.TypeEnum == myEnum ? 1 
      : x.TypeEnum == TypeEnum.Default ? -1 
      : y.TypeEnum == TypeEnum.Default ? 1 
      : x.TypeEnum.CompareTo(y.TypeEnum); 
    } 
    else 
     return x.Name.CompareTo(y.Name); 
}; 
Array.Sort(someArray, compareByTypeEnum); 
var result = someArray.Where(x => x.TypeEnum == TypeEnum.Default || x.TypeEnum == TypeEnum.Other) 
         .GroupBy(x => x.Name) 
         .Select(x => x.First()); 
+0

+1打我的一拳。我剛剛就是這個意思。 – TylerOhlsen

0

試試這個,使用DefaultIfEmpty("Default")

 var someArray = new List<TestClass> 
          { 
           new TestClass {Name = "Some Class", TypeEnum = "Default"}, 
           new TestClass {Name = "Some Class", TypeEnum = "Other"}, 
           new TestClass {Name = "Some Class 2", TypeEnum = "Default"}, 
           new TestClass {Name = "Some Class 2", TypeEnum = "Other"}, 
           new TestClass {Name = "Some Class 3", TypeEnum = "Default"} 
          }; 

     string myEnum = "Other"; 

     var result = someArray.GroupBy(t => t.Name). 
        Select(t => new TestClass 
         { 
          Name = t.Key, 
          TypeEnum = t.Select(s => s.TypeEnum).Where(p => p == myEnum).DefaultIfEmpty("Default").FirstOrDefault() 
         }); 
1

可以使用的GroupBy得到一個字典做這方面的工作。可能它也更簡單。

List<Tuple<string, string>> lst = new List<Tuple<string, string>>(); 
lst.Add(new Tuple<string, string>("Some Class", "Default")); 
lst.Add(new Tuple<string, string>("Some Class", "Other")); 
lst.Add(new Tuple<string, string>("Some Class 2", "Default")); 
lst.Add(new Tuple<string, string>("Some Class 2", "Other")); 
lst.Add(new Tuple<string, string>("Some Class 3", "Default")); 

var dict = lst.GroupBy(g => g.Item1) 
       .ToDictionary(g => g.Key, k => k.Select(s => s.Item2) 
               .Where(p => p == "Other") 
               .DefaultIfEmpty("Default") 
               .First()); 

或者你的情況:

TypeEnum myEnum = "Other" 
var dict = lst.GroupBy(g => g.Name) 
    .ToDictionary(g => g.Key, k => k.Select(s => s.TypeEnum) 
           .Where(p => p == myEnum) 
           .DefaultIfEmpty("Default") 
           .First()); 
1

鮮明不工作,你所希望的方式和這裏的原因,你可能永遠無法得到它本身的工作。獨特之處在於使用散列表來查找唯一值。它按順序將每個項目添加到哈希表中,並省略添加與散列表中已存在的任何其他值相同的哈希值。

這意味着你的項目有關的事項的順序,因爲數組中的第一項獲勝。我們可以通過在調用distinct之前修改列表的順序來利用這個優勢。修改@風的solution一點點,我們得到這個...

var result = someArray.OrderBy(key => key.TypeEnum, new TypeEnumComparer(myEnum)) 
    .Distinct(new LambdaEqualityComparer<SomeClass>((x, y) => x.Name == y.Name)); 

與修改比較器...

public class TypeEnumComparer : Comparer<TypeEnum> 
{ 
    private TypeEnum _preference; 

    public TypeEnumComparer(TypeEnum preference) 
     : base() 
    { 
     _preference = preference; 
    } 

    public override int Compare(TypeEnum x, TypeEnum y) 
    { 
     if (x == y)    return 0; 
     if (x == _preference)  return -1; 
     if (y == _preference)  return 1; 
     if (x == TypeEnum.Default) return -1; 
     if (y == TypeEnum.Default) return 1; 

     return x.CompareTo(y); 
    } 
}