Сортировать список C # в произвольном порядке - PullRequest
1 голос
/ 23 ноября 2011

У меня есть список C # IE 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 ;, который имеетIE 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 ]

3 голосов
/ 23 ноября 2011

Стандартный метод сортировки не поможет вам в этом.
Вам нужно что-то вроде настраиваемого метода сортировки Round Robin.Например, это вид , как пузырьковая сортировка.

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;
    }
}
3 голосов
/ 23 ноября 2011

Ваш алгоритм не поддается функции Sort или OrderBy, потому что по двум отдельным элементам невозможно определить, какой из них будет первым.

Вам нужно взять неупорядоченный 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++;
        }
    }
0 голосов
/ 23 ноября 2011

Угадаю, но если вы хотите смоделировать четыре сумки.Один из каждого типа.и затем выбирайте по одному из каждого по порядку, пока все пакеты не станут пустыми.

Сделайте тип еды enum, чтобы он находился в правильном порядке.

сбросьте ваш список в SortedList> что-то вроде

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);
    }  
}

не проверено, но это вроде правильно, может быть аккуратнее и быстрее, но вы можете посмотреть на это, когда этоделает то, что вы хотите.

Почти как странный алгоритм упаковки мусорного ведра.Каждая корзина будет содержать одну из вещей, оставленных в этом порядке.

0 голосов
/ 23 ноября 2011

Я думаю, вы захотите реализовать свой собственный объект IEnumerable для этого.Я бы начал со списка для каждого типа пищи, или, что еще лучше, со словарем, в котором хранится список для каждого типа пищи.Вам нужно будет обработать собственное перечисление.Это означает отслеживание вашей текущей позиции в каждом списке и того, какой был последний запрошенный тип пищи.Затем вы просто находите этот список в словаре и получаете следующее значение, если оно есть, и обновляете lastRequestedFoodType.Просто убедитесь, что вы возвращаете свой собственный IEnumerator вместо того, который принадлежит одному из списков в словаре.Это в основном позволяет вам перебирать все ваши списки в словаре.Если у вас нет элементов в одном списке, просто пропустите его и перейдите к следующему.Когда вы дойдете до конца всех списков, все готово.

Добавление элементов таким способом должно быть довольно простым, но вставить их или изменить порядок будет сложно.

Поскольку вы на самом деле не сортируете, а упорядочиваете, на самом деле для этого нет ничего встроенного.

0 голосов
/ 23 ноября 2011

Вы можете использовать метод 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

(необходимо назначить какую-либо систему сравнения для различных типов продуктов)

Удачи

0 голосов
/ 23 ноября 2011

Это может помочь.

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

По сути, вы можете создать свой собственный класс IComparable для настройки сортировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...