按自定义顺序对字典排序

时间:2017-11-15 13:22:42

标签: c# dictionary

这是指

Sort a list by a custom order

我会找一个类似的例子......我有一个包含用户的词典

public class UserInfo
{
    public string Name { get; set; }

    public string Location { get; set; }
}

数据:

private Dictionary<string, UserInfo> users = new Dictionary<string, UserInfo>(); // id + user

以及可能的位置列表

        private string[] locations = {
            "europe",
            "america",
            "asia",
            "africa"
        };

如何按这些位置订购此词典?

应该有输出

  

// ...所有欧洲人

     

// ...所有美国人

     

// ...所有亚洲人

     

// ...所有非洲人

致电

    Dictionary<string, UserInfo> sortedUsers = ; // Sorting the dict "users" by locations

    foreach (KeyValuePair<string, UserInfo> info in sortedUsers)
    {
        Console.WriteLine("L: " + info.Value.Location + " N: " + info.Value.Name);
    }

5 个答案:

答案 0 :(得分:1)

字典不是有序集合,但似乎您希望订购它Values

var orderedUsersByLocation = users.Values.OrderBy(ui => ui.Location);

如果您想List<UserInfo>使用ToList

List<UserInfo> result = orderedUsersByLocation.ToList();

也许我没有得到string[]可能位置的含义,您是说这个数组指定了顺序,那些位置是UserInfo.Location中的可能位置吗?

private string[] locations = {
        "europe",
        "america",
        "asia",
        "africa"
    };

var orderedUsersByLocation = users.Values
    .OrderBy(ui => Array.IndexOf(locations, ui.Location));

如果某个位置可能未包含在该数组中Array.IndexOf返回-1,那么这些条目将是第一个。如果可能,您希望它们列在最后:

var orderedUsersByLocation = users.Values
    .Select(ui => new { UserInfo = ui, Index = Array.IndexOf(locations, ui.Location)})
    .OrderBy(x => x.Index == - 1 ? int.MaxValue : x.Index)
    .Select(x => x.UserInfo);

答案 1 :(得分:1)

词典不是ICollection,你不能使用OrderBy(),但是如果转换为list,你可以实现IComparer功能:

private class SortCustom : IComparer
{
   private static string[] locations = {
        "europe",
        "america",
        "asia",
        "africa"
    };
   int IComparer.Compare(UserInfo a, UserInfo b)
   {
      return 
           Array.FindIndex(locations, row => row == a.Value.Location).CompareTo(
           Array.FindIndex(locations, row => row == b.Value.Location));
   }
}

被叫:

sortedUsers.OrderBy(x => x, new SortCustom());

答案 2 :(得分:0)

您不对字典进行排序,将其值作为列表获取并根据您的条件对值进行排序,如果条件是字典,则最常做的是:

Dictionary<string,int> locations = new Dictionary<string,int>();
locations["europe"] = 0;
locations["america"] = 1;
locations["asia"] = 2;
locations["africa"] = 3;

//formatted to fit in SO without scrolling
var sortedUsers = 
  users.Values.OrderBy(
    u => locations.ContainsKey(u.Location) ? locations[u.Location] : 999999
  );

foreach (UserInfo info in sortedUsers)
{
    Console.WriteLine("L: " + info.Value.Location + " N: " + info.Value.Name);
}

答案 3 :(得分:0)

您可以尝试按照&#34;自定义位置订单&#34; 进行订购:

string[] locations = 
{
    "europe",
    "america",
    "asia",
    "africa"
};

Dictionary<string, UserInfo> sortedUsers = new Dictionary<string, UserInfo>();

foreach (var item in locations)
{
    sortedUsers = sortedUsers.Concat(users.Where(u => u.Value.Location == item)
                             .ToDictionary(d => d.Key, d => d.Value))
                             .ToDictionary(d => d.Key, d => d.Value);
}

答案 4 :(得分:0)

您最初可以使用IComparer构建排序列表,然后从中创建一个字典:

    void Main()
    {
        var d = GetDictionary();
    }

    Dictionary<string,UserInfo> GetDictionary()
    {
        var l = new List<UserInfo>() {
            new UserInfo("One", "There"),
            new UserInfo("Two", "SomewhereB"),
            new UserInfo("Three", "SomewhereA"),
            new UserInfo("Four", "Here")
        };
        var comp = new UserInfoComparer();
        l.Sort(comp);
        return  l.ToDictionary( e => e.Name);
    }

    public class UserInfo
    {
        public string Name { get; set; }
        public string Location { get; set; }
        public UserInfo(string name, string location)
        {
            Name = name;
            Location = location;
        }
    }
    public class UserInfoComparer: IComparer<UserInfo>{
        public int Compare(UserInfo x, UserInfo y)
        {
            var r = x.Location.CompareTo(y.Location);
            if (r == 0)
            {
                r = x.Name.CompareTo(y.Name);
            }
            return r;
        }
    }