按任意顺序对列表C#进行排序

时间:2011-11-23 17:13:39

标签: c# list sorting

我有一个C#List I.E. List<Food> x = new List<Food> () ;

此列表中填充了此类

public class Food {
           public string id { get; set; }
           public string idUser { get; set; }               
           public string idType { get; set; } 
          //idType could be Fruit , Meat , Vegetable , Candy 
           public string location { get; set; }    
}

现在我有了未排序的 List<Food> list ;,其中有I.E. 15个元素。 有8种蔬菜类型,3种水果类型,1种肉类型,1种糖果类型

我会对此进行排序,以便以这种方式排序:

1° : Food.idType Fruit 
2° : Food.idType Vegetables 
3° : Food.idType Meat
4° : Food.idType Candy
5° : Food.idType Fruit
6° : Food.idType Vegetables
7° : Food.idType Fruit //Becouse there isnt more Meat so i insert the 
                       //next one which is Candy but also this type is empty 
                       //so i start from begin : Fruit
8° : Food.idType Vegetables
9° : Food.idType Vegetables // For the same reason of 7°
10 ° Food.idType Vegetables
......
....
....
15 : Food.idType Vegetables

我找不到这样做的规则。是否有linq或List.Sort指令帮助我以这种方式订购列表?

更新我更改了idType的返回值,现在返回int类型而不是字符串  1 =蔬菜,2 =水果,3 =糖果4 =肉

6 个答案:

答案 0 :(得分:3)

您的算法不适用于SortOrderBy函数,因为无法通过查看两个单独的元素来判断哪个元素将首先出现。

您需要做的是在List字段上执行无序GroupBy并执行idType。这会给你一套水果,一套蔬菜等等。然后按组(idType)对组进行排序。最后,您需要交错每个组的元素,一旦项目用完就省去一个组。

这是一个假设idType符合您希望选择输出的顺序的示例:

    public static IEnumerable<Food> InterleaveFoods(IEnumerable<Food> source)
    {
        var groups = (from food in source
                      group food by food.idType into foodGroup
                      orderby foodGroup.Key
                      select foodGroup.ToArray())
                     .ToList();

        int i = 0;
        while (groups.Any())
        {
            for (int group = 0; group < groups.Count; group++)
            {
                if (i < groups[group].Length)
                    yield return groups[group][i];
                else
                {
                    // group is empty; remove it
                    groups.RemoveAt(group);
                    group--;
                }
            }
            i++;
        }
    }

答案 1 :(得分:3)

标准的排序方法不会为你削减这一点 你需要像定制Round Robin sort methd这样的东西。例如 这是类似的冒泡类型。

public enum FoodType
{
    Fruit,
    Veg,
    Meat,
    Candy
}

public class Food
{
    public FoodType Type;
    public string Name { get; set; }
}


void RoundRobinSort(List<Food> foods)
{
    var typeValues = (FoodType[])Enum.GetValues(typeof(FoodType));
    int nextType = 0;
    for (int i = 0; i < foods.Count - 1; i++)
    {
        if (foods[i].Type != typeValues[nextType])
        {
            int itemToSwap = -1;
            int loopGuard = 0;
            while (itemToSwap == -1 && loopGuard <= typeValues.Length)
            {
                itemToSwap = foods.FindIndex(i, f => f.Type == typeValues[nextType]);
                if(itemToSwap == -1)
                    nextType = (nextType + 1) % typeValues.Length;
                loopGuard++;
            }
            if (itemToSwap == -1)
                throw new Exception("Should never happen, Put a meaningful message here");

            if (itemToSwap != i)
            {
                var temp = foods[itemToSwap];
                foods[itemToSwap] = foods[i];
                foods[i] = temp;
            }
        }
        nextType = (nextType + 1) % typeValues.Length;
    }
}

答案 2 :(得分:0)

这可能会有所帮助。

http://www.switchonthecode.com/tutorials/csharp-snippet-tutorial-custom-list-sorting

基本上,您可以创建自己的IComparable类来自定义排序。

答案 3 :(得分:0)

您可以使用List.Sort方法,但需要实现相等比较器。以下是基于您的类似问题的示例

http://devpinoy.org/blogs/keithrull/archive/2007/03/23/sorting-a-generic-list-of-object-in-c-using-icomparable-and-anonymous-delegates.aspx

(您需要为各种食物类型指定一些比较系统)

祝你好运

答案 4 :(得分:0)

我认为你会想要为此实现自己的IEnumerable对象。我会从每种食物类型的列表开始,或者更好的是,一种存储每种食物类型列表的字典。您需要处理自己的枚举。这意味着要跟踪每个列表中的当前位置以及所请求的最后一种食物类型。然后,您只需在字典中找到该列表,然后获取下一个值,并更新lastRequestedFoodType。只需确保您返回自己的IEnumerator而不是属于字典中某个列表的IEnumerator。这基本上允许您循环遍历字典中的所有列表。如果您不在一个列表中的项目,只需跳过它并继续下一个。当你到达所有列表的末尾时,你就完成了。

以这种方式添加项目应该非常简单,但插入它们或更改顺序将很难。

由于你没有真正排序,你正在安排,没有真正内置的东西。

答案 5 :(得分:0)

在这里猜测,但如果你想模特儿 四袋。 每种类型之一。 然后按顺序从每个中选择一个,直到所有行李都是空的。

使食物类型为枚举,所以它的顺序正确。

将您的列表转储到SortedList&gt;

之类的东西
SortedList<enumFoodType,List<Food>> sortedFood = new     SortedList<enumFoodType,List<Food>>
foreach(Food f in x)
{
  if (sortedFood.ContainsKey(f.foodType))
  {
    sortedFood[f.foodType].Add(f);
  }
else
{
  sortedfood.Add(f.foodType,f);
}

会这样做。

然后

List<Food> chosenX  = new List<Food>();
while (sortedFood.Count > 0)
{
  foreach(enumFoodType ft in sortedFood.Keys)
  {
    if (sortedKeys[ft].Count > 0)
    {
      chosenX.Add(sortedKeys[ft][0];
      sortedKeys[ft].RemoveAt(0);
    }  
}

未经检查,但它有点正确,可能更整洁,更快,但你可以在它做你想要的时候看看它。

几乎像一个奇怪的bin打包算法这一个。 每个bin都将包含按此顺序保留的每个东西中的一个。