LINQ эквивалент foreach для IEnumerable < T >

Примечание: это работает только для низких символов, то есть ниже 0x8000. Это работает для всех символов ASCII.

Я бы сделал XOR каждый charAt () для создания новой строки. Как

String s, key;

StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length(); i++)
    sb.append((char)(s.charAt(i) ^ key.charAt(i % key.length())));
String result = sb.toString();

В ответ на комментарий @ user467257

Если ваш ввод / вывод - utf-8, а вы xor «a» и «æ», вы остаетесь с недопустимой строкой utf-8, состоящей из одного символа (десятичный 135, символ продолжения).

Это значения char, которые являются xor'ed, но байтовые значения, и это создает символ, который является кодировкой UTF-8.

public static void main(String... args) throws UnsupportedEncodingException {
    char ch1 = 'a';
    char ch2 = 'æ';
    char ch3 = (char) (ch1 ^ ch2);
    System.out.println((int) ch3 + " UTF-8 encoded is " + Arrays.toString(String.valueOf(ch3).getBytes("UTF-8")));
}

печатает

135 UTF-8 encoded is [-62, -121]
677
задан abatishchev 1 September 2010 в 08:52
поделиться

6 ответов

Нет никакого расширения ForEach для IEnumerable; только для List<T>. Таким образом, Вы могли сделать

items.ToList().ForEach(i => i.DoStuff());

, С другой стороны, пишут Ваш собственный метод расширения ForEach:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}
811
ответ дан huysentruitw 1 September 2010 в 08:52
поделиться

Fredrik обеспечил фиксацию, но это может быть достойно рассмотрения, почему это не находится в платформе для запуска с. Я полагаю, что идея состоит в том, что операторы запроса LINQ должны быть без побочных эффектов, согласовавшись с довольно функциональным способом посмотреть на мир. Очевидно ForEach является точно противоположным - просто основанная на побочном эффекте конструкция.

Но это вовсе не значит это - плохая вещь сделать - просто думающий о философских причинах позади решения.

347
ответ дан Jon Skeet 1 September 2010 в 08:52
поделиться

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

Примите во внимание следующее:

   public class Element {}

   public Enum ProcessType
   {
      This = 0, That = 1, SomethingElse = 2
   }

   public class Class1
   {
      private Dictionary<ProcessType, Action<Element>> actions = 
         new Dictionary<ProcessType,Action<Element>>();

      public Class1()
      {
         actions.Add( ProcessType.This, DoThis );
         actions.Add( ProcessType.That, DoThat );
         actions.Add( ProcessType.SomethingElse, DoSomethingElse );
      }

      // Element actions:

      // This example defines 3 distict actions
      // that can be applied to individual elements,
      // But for the sake of the argument, make
      // no assumption about how many distict
      // actions there may, and that there could
      // possibly be many more.

      public void DoThis( Element element )
      {
         // Do something to element
      }

      public void DoThat( Element element )
      {
         // Do something to element
      }

      public void DoSomethingElse( Element element )
      {
         // Do something to element
      }

      public void Apply( ProcessType processType, IEnumerable<Element> elements )
      {
         Action<Element> action = null;
         if( ! actions.TryGetValue( processType, out action ) )
            throw new ArgumentException("processType");
         foreach( element in elements ) 
            action(element);
      }
   }

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

1
ответ дан 22 November 2019 в 21:37
поделиться

Я взял метод Фредрика и изменил возвращаемый тип.

Таким образом, метод поддерживает отложенное выполнение, как и другие методы LINQ.

EDIT: Если это не было ясно, любое использование этого метода должно заканчиваться ToList() или любым другим способом заставить метод работать с полным перечислимым. В противном случае действие не будет выполнено!

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach (T item in enumeration)
    {
        action(item);
        yield return item;
    }
}

И вот тест, который поможет это увидеть:

[Test]
public void TestDefferedExecutionOfIEnumerableForEach()
{
    IEnumerable<char> enumerable = new[] {'a', 'b', 'c'};

    var sb = new StringBuilder();

    enumerable
        .ForEach(c => sb.Append("1"))
        .ForEach(c => sb.Append("2"))
        .ToList();

    Assert.That(sb.ToString(), Is.EqualTo("121212"));
}

Если вы удалите ToList() в конце, вы увидите, что тест не выполняется, поскольку StringBuilder содержит пустую строку. Это происходит потому, что ни один метод не заставил ForEach перечислять.

21
ответ дан 22 November 2019 в 21:37
поделиться

Еще один ForEach Пример

public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
    var workingAddresses = new List<AddressEntry>();

    addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));

    return workingAddresses;
}
0
ответ дан 22 November 2019 в 21:37
поделиться

ForEach предназначен для создания побочных эффектов. IEnumerable предназначен для ленивого перечисления набора.

Это концептуальное различие вполне заметно, если его рассмотреть.

SomeEnumerable.ForEach(item=>DataStore.Synchronize(item));

Это не будет выполнено, пока вы не сделаете "count" или "ToList()" или что-то в этом роде. Это явно не то, что выражено.

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

6
ответ дан 22 November 2019 в 21:37
поделиться
Другие вопросы по тегам:

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