При сортировке списка по полю типа int можно ли сортировать значение 310 между 41 и 39? - PullRequest
0 голосов
/ 24 января 2019

У меня есть список объектов, которые я сортирую по полю их идентификаторов, но идентификаторы генерируются, чтобы идти 38, 39, 310, 41, 42 и т. Д. Есть ли функция LINQ для обработки такого рода вещей?

Я пробовал цикл после сортировки, чтобы перемещаться по объектам в моем списке, но это слишком большой удар по производительности, чтобы быть жизнеспособным решением.Я также пытался поменять идентификаторы с 310 на 40, когда я их извлекаю, и переключить их обратно после сортировки, но мне сказали, что это также невозможно, на случай, если они начнут двигаться 39, 310, 40 в будущем.Я также спросил другого разработчика, может ли он переключить генерацию идентификатора с 39 на 40, он сказал, что это устаревший код, к которому он не хочет прикасаться.

data.OrderByDescending(x => x.Number).ThenByDescending(x => x.Value)

Текущий результат выглядит так: 310, 210, 110, 39, 38 и т. Д.

Мне бы хотелось, чтобы это выглядело: 42, 41, 310, 39, 38, ..., 31, 210, 29 и т. Д.

Ответы [ 4 ]

0 голосов
/ 24 января 2019

Вы можете использовать IComparer для прямой сортировки списка.

public class LegacyIdDescendingComparer : IComparer<DataClass>
{
    public LegacyIdDescendingComparer() { }

    public int Compare(DataClass x, DataClass y)
    {
        if (x.ID == y.ID)
        {
            return 0;
        }
        // The last digit, forgive my naming conventions
        // If the number ends with 10 then the last digit is ten else it is whatever the value in units place
        // I did this to make this work with the following case: 28, 29, 210, 30, 31
        // 210 will be 10, 31 will be 1
        var x_tens = x.ID % 100 == 10 ? 10 : x.ID % 10;
        var y_tens = y.ID % 100 == 10 ? 10 : y.ID % 10;

        // The number divided by 10
        // 210 is 2, 29 is also 2
        var x_quo = x.ID % 100 == 10 ? x.ID / 100 : x.ID / 10;
        var y_quo = y.ID % 100 == 10 ? y.ID / 100 : y.ID / 10;

        if (x_quo > y_quo)
        {
            return -1;
        }
        if (x_quo == y_quo)
        {
            return y_tens.CompareTo(x_tens);
        }
        return 1;
    }
}

Затем вы можете отсортировать список в порядке убывания, вызвав Sort on

data.Sort(new LegacyIdDescendingComparer());

Это позволит отсортировать список данных в порядке убывания ID.

Вы можете проверить это здесь: https://ideone.com/oKN1Qs

0 голосов
/ 24 января 2019

Мне кажется, вы просто пытаетесь расставить приоритеты первым числом в целом числе, а не числом в целом. Если это так, может быть, это будет работать для вас?

var list = new List<int>() { 210, 29, 42, 310, 39, 38, 41, 31 };
var sortedList = list.OrderByDescending(x => x.ToString()[0]).ThenByDescending(x => x);

// 42, 41, 310, 39, 38, 31, 210, 29

Если вам нужно поддерживать 1010 и 101, как указано в комментариях, это становится немного сложнее, но вы все равно можете использовать аналогичную стратегию. Хотя в этот момент решение Дираджа начинает выглядеть более привлекательным.

var list = new List<int>() { 210, 29, 42, 310, 39, 38, 41, 31, 99, 101, 910, 1010 };
var sortedList = list.OrderByDescending(x => Int32.Parse(x.ToString().Substring(0, x.Length() - (x % 10 == 0 ? 2 : 1))))
    .ThenByDescending(x => x);

// 1010, 101, 910, 99, 42, 41, 310, 39, 38, 31, 210, 29

IntExtensions.cs

public static class IntExtensions
{
    public static int Length(this int value)
    {
        value = Math.Abs(value);
        if (value < 10) return 1;
        if (value < 100) return 2;
        if (value < 1000) return 3;
        if (value < 10000) return 4;
        if (value < 100000) return 5;
        if (value < 1000000) return 6;
        if (value < 10000000) return 7;
        if (value < 100000000) return 8;
        if (value < 1000000000) return 9;
        return 10;
    }
}
0 голосов
/ 24 января 2019

Я бы рекомендовал разбить числа на массивы символов и выполнить первоначальную сортировку по первому символу.

Затем проанализируйте оставшиеся символы обратно в int для сортировки по убыванию. Вот так

string[] id = {"38", "39", "310", "41", "42"}
id.OrderBy(x => x.ToCharArray()[0]).ThenByDescending(x => int.Parse(x.Remove(0, 1)))
0 голосов
/ 24 января 2019

Итак, если число делится точно на 10, мы должны разделить на 100, добавить 1 и умножить на 10, чтобы получить «реальное» значение, которое будет естественным образом сортироваться 1 :

data.OrderByDescending(x => {
  if(x.Number%10!=0) return x.Number;
  return ((x.Number / 100) + 1) * 10;
}).ThenByDescending(x => x.Value)

Я предполагаю, что Number равно int и разрешает правилам целочисленного деления "избавиться" от надоедливых 0.1 после деления.

1 То есть 310 следует рассматривать как 40, 510 следует рассматривать как 60 и т. Д.

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