Эффективно удалить последние нули в списке целых чисел (C# или vb.net)

Я удаляю самые правые нули в списке целых чисел (они могут быть только 0 или 1) следующим образом:

For i As Integer = Product.Count - 1 To 0 Step -1
    If Product(i) = 0 Then
        Product.RemoveAt(i)
    Else
        Exit For
    End If
Next

Не могли бы вы предложить решение, которое было бы менее неудобным и, возможно, более эффективным из того, что я сейчас делаю?

Если возможно, я хотел бы также увидеть альтернативное решение для сохранения 1 нуля, если список содержит только 1 ноль и 1 ноль. Спасибо (язык, C# из vb.net не имеет значения).

(PS. Обратите внимание, что "эффективность", которая является частью вопроса, является объективным критерием, не основанным на мнениях.)

4 ответа

Решение

Я бы сделал это:

public void RemoveTrailingZeros( List<int> digits )
{
  int i = digits.Count ;
  while ( --i >= 0 && digits[i] == 0 )
  {
    digits.RemoveAt(i) ;
  }
  return ;
}

Еще аккуратнее:

static void RemoveTrailingZeroes( List<int> digits )
{
  int i = 1 + digits.FindLastIndex( x => x != 0 ) ;
  digits.RemoveRange(i,digits.Count-i) ;
  return ;
}

Если значения могут быть только 0 или 1, вы можете найти последнюю 1 и удалить все после этого.

    Dim index As Integer
    index = Product.LastIndexOf(1) + 1
    Product.RemoveRange(index, Product.Count - index)

Если список содержит только 0, индекс будет равен 0, поэтому вы можете добавить if if прямо перед RemoveRange.

    Dim index As Integer
    index = Product.LastIndexOf(1) + 1
    If index = 0 Then index = 1
    Product.RemoveRange(index, Product.Count - index)

(Может произойти сбой, если в списке нет элементов)

Обновить

Поскольку он ищет 1, индексом первого 0 будет индекс, возвращаемый +1. Это также решает проблему с функцией, возвращающей -1, когда все нули.

Я не уверен, что это более элегантно, но он использует LINQ!

int lastOne = i.IndexOf(i.Last(n => n == 1));
List<int> trimmedList = i.Take(lastOne + 1); //Account for zero-based index

Чтобы получить один ноль, я бы использовал LastOrDefault

int lastOne = i.IndexOf(i.LastOrDefault(n => n == 1));
List<int> trimmedList = i.Take(lastOne + 1); //Account for zero-based index

Безусловно, самый "крутой" метод LINQ, предложенный Алексеем Левенковым:

Reverse().SkipWhile(i=> i==0).Reverse();

Это удалит один нулевой случай, в этом случае я бы использовал троичный:

i.All(n => n == 0) ? i.Take(1) : i.Reverse().SkipWhile(i=> i==0).Reverse();

Просто обрезать:)

Product.TrimEnd('0');
Другие вопросы по тегам