Позвольте Работе SequenceEqual для списка

Кодирование строки и использование len для результата прекрасно работает, как показали другие ответы. Нужно создать одноразовую копию строки - если вы работаете с очень большими строками, это может быть неоптимально (хотя я не считаю 1024 байта большими большими ). Структура UTF-8 позволяет очень легко получить длину каждого символа, даже не кодируя его, хотя все еще может быть проще кодировать один символ. Здесь я представляю оба метода, они должны давать одинаковый результат.

def utf8_char_len_1(c):
    codepoint = ord(c)
    if codepoint <= 0x7f:
        return 1
    if codepoint <= 0x7ff:
        return 2
    if codepoint <= 0xffff:
        return 3
    if codepoint <= 0x10ffff:
        return 4
    raise ValueError('Invalid Unicode character: ' + hex(codepoint))

def utf8_char_len_2(c):
    return len(c.encode('utf-8'))

utf8_char_len = utf8_char_len_1

def utf8len(s):
    return sum(utf8_char_len(c) for c in s)
5
задан Mehrdad Afshari 5 July 2009 в 22:43
поделиться

3 ответа

Разбейте его на множество простых запросов, а затем снова сложите эти запросы.

Начнем с создания последовательности элементов, совпадающих по имени:

var nameMatches = from item in itemList where item.Name == p.Name select item;

Нам нужно сравнить эти элементы с последовательностью имен в подэлементах p. Что это за последовательность? Напишите запрос:

var pnames = from subitem in p.SubItems select subitem.Name;

Теперь вы хотите найти все элементы из nameMatches, которым соответствует последовательность имен. Как вы собираетесь получить последовательность имен? Что ж, мы только что увидели, как это сделать с помощью pnames, поэтому сделайте то же самое:

var matches = from item in nameMatches
              let subitemNames = 
                  (from subitem in item.SubItems select subitem.Name)
              where pnames.SequenceEqual(subitemNames)
              select item;

А теперь вы хотите знать, есть ли совпадения?

return matches.Any();

Это должно работать нормально, как есть. Но если вы хотите стать настоящим фанатом, вы можете написать все в одном большом запросе!

return (
    from item in itemList
    let pnames = 
        (from psubitem in p.SubItems select psubitem.Name)
    let subitemNames = 
        (from subitem in item.SubItems select subitem.Name)
    where item.Name == p.Name
    where pnames.SequenceEqual(subitemNames)
    select item).Any();

И готово. Проще простого! Просто помните, разбейте его на маленькие шаги, решайте каждую проблему индивидуально, а затем составляйте решение из небольших результатов.

12
ответ дан 18 December 2019 в 13:18
поделиться

Вы смотрели на реализацию IComparer в элементе?

1
ответ дан 18 December 2019 в 13:18
поделиться

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

    public override bool Equals(object obj)
    {
        return this.Name == (obj as Item).Name;
    }
    public override int GetHashCode()
    {
        return this.Name.GetHashCode();
    }
    public bool Check(Item obj)
    {
        if (this.Name != obj.Name)
            return false;
        //if the lists arent of the same length then they 
        //obviously dont contain the same items, and besides 
        //there would be an exception on the next check
        if (this.SubItems.Count != obj.SubItems.Count)
            return false;
        for (int i = 0; i < this.SubItems.Count; i++)
            if (this.SubItems[i] != obj.SubItems[i])
                return false;
        return true;
    }
1
ответ дан 18 December 2019 в 13:18
поделиться
Другие вопросы по тегам:

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