Список. Вид в C#: компаратор, называемый с несуществующим объектом

Как @AaronHall, я попал сюда в поисках кусков примерно одинакового размера. Есть разные интерпретации этого. В моем случае, если желаемый размер N, я бы хотел, чтобы каждая группа имела размер> = N. Таким образом, сироты, созданные в большинстве из вышеперечисленного, должны быть перераспределены на другие группы.

Это можно сделать, используя:

def nChunks(l, n):
    """ Yield n successive chunks from l.
    Works for lists,  pandas dataframes, etc
    """
    newn = int(1.0 * len(l) / n + 0.5)
    for i in xrange(0, n-1):
        yield l[i*newn:i*newn+newn]
    yield l[n*newn-newn:]

(из Разделение списка на N частей приблизительно равной длины ), просто назвав его nChunks (l, l / n). ) или nChunks (л, пол (л / н))

20
задан cbp 11 March 2010 в 06:58
поделиться

6 ответов

Эта проблема возникает, когда функция сравнения несовместима, так что x

Вот пример, который воспроизводит проблему. Здесь это вызвано патологической функцией сравнения compareStrings. Это зависит от начального состояния списка: если вы измените начальный порядок на «C», «B», «A», то исключений не будет.

Я бы не назвал это ошибкой в ​​функции сортировки - это просто требование согласованности функции сравнения.

using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var letters = new List<string>{"B","C","A"};

        letters.Sort(CompareStrings);
    }

    private static int CompareStrings(string l, string r)
    {
        if (l == "B")
            return -1;

        return l.CompareTo(r);
    }
}
23
ответ дан 30 November 2019 в 00:40
поделиться

Вы уверены, что проблема не в том, что SomeProp равен null ?

В частности, со строками или Nullable значений.

Для строк было бы лучше использовать:

list.Sort((x, y) => string.Compare(x.SomeProp, y.SomeProp));

(edit)

Для нулевой безопасной оболочки вы можете использовать Comparer .Default - например, чтобы отсортировать список по свойству:

using System;
using System.Collections.Generic;
public static class ListExt {
    public static void Sort<TSource, TValue>(
            this List<TSource> list,
            Func<TSource, TValue> selector) {
        if (list == null) throw new ArgumentNullException("list");
        if (selector == null) throw new ArgumentNullException("selector");
        var comparer = Comparer<TValue>.Default;
        list.Sort((x,y) => comparer.Compare(selector(x), selector(y)));
    }
}
class SomeType {
    public override string ToString() { return SomeProp; }
    public string SomeProp { get; set; }
    static void Main() {
        var list = new List<SomeType> {
            new SomeType { SomeProp = "def"},
            new SomeType { SomeProp = null},
            new SomeType { SomeProp = "abc"},
            new SomeType { SomeProp = "ghi"},
        };
        list.Sort(x => x.SomeProp);
        list.ForEach(Console.WriteLine);
    }
}
3
ответ дан 30 November 2019 в 00:40
поделиться

Ответ Марка полезен. Я согласен с ним, что NullReference возникает из-за вызова CompareTo для нулевого свойства. Без класса расширения вы можете:

mylist.Sort((x, y) => 
      (Comparer<SomePropType>.Default.Compare(x.SomeProp, y.SomeProp)));

, где SomePropType - это тип SomeProp

0
ответ дан 30 November 2019 в 00:40
поделиться

В целях отладки вы хотите, чтобы ваш метод был нулевым. (или, по крайней мере, перехватить исключение null-ref. и обработать его жестко запрограммированным способом). Затем используйте отладчик, чтобы посмотреть, какие другие значения сравниваются, в каком порядке и какие вызовы завершаются успешно или неуспешно.

Тогда вы найдете свой ответ и сможете удалить нулевую безопасность.

0
ответ дан 30 November 2019 в 00:40
поделиться

Можете ли вы запустить этот код ...

mylst.Sort((i, j) =>
              {
                  Debug.Assert(i.SomeProp != null && j.SomeProp != null);
                  return i.SomeProp.CompareTo(j.SomeProp);
              }
         );
0
ответ дан 30 November 2019 в 00:40
поделиться

Я сам наткнулся на эту проблему и обнаружил, что она связана со свойством NaN в моем вводе. Вот минимальный тестовый пример, который должен вызвать исключение:

public class C {

    double v;

    public static void Main() {
        var test =
            new List<C> { new C { v = 0d },
                          new C { v = Double.NaN },
                          new C { v = 1d } };
        test.Sort((d1, d2) => (int)(d1.v - d2.v));
    }

}
0
ответ дан 30 November 2019 в 00:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: