Попарное повторение в C# или перечислителе раздвижного окна

Как указано в документации React, нет гарантии того, что setState запущен синхронно, поэтому ваш console.log может вернуть состояние до его обновления.

Майкл Паркер упоминает о передаче обратного вызова внутри setState. Другой способ обработки логики после изменения состояния осуществляется с помощью метода жизненного цикла componentDidUpdate, который является методом, рекомендованным в документах React.

Обычно мы рекомендуем использовать для этой логики componentDidUpdate ().

Это особенно полезно, когда могут быть последовательные setState s, и вы хотели бы запустить ту же функцию после каждого изменения состояния. Вместо добавления обратного вызова к каждому setState, вы можете поместить функцию внутри componentDidUpdate с конкретной логикой внутри, если необходимо.

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}
47
задан f3lix 23 February 2009 в 13:17
поделиться

7 ответов

Вместо того, чтобы требовать тип кортежа (пары), почему бы просто не принять селектор:

public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector)
{
    TSource previous = default(TSource);

    using (var it = source.GetEnumerator())
    {
        if (it.MoveNext())
            previous = it.Current;

        while (it.MoveNext())
            yield return resultSelector(previous, previous = it.Current);
    }
}

Что позволяет вам пропустить промежуточный объект, если вы хотите:

string[] items = new string[] { "a", "b", "c", "d" };
var pairs = items.Pairwise((x, y) => string.Format("{0},{1}", x, y));

foreach(var pair in pairs)
    Console.WriteLine(pair);

Или вы можете использовать анонимный тип:

var pairs = items.Pairwise((x, y) => new { First = x, Second = y });
37
ответ дан 7 November 2019 в 13:06
поделиться

Существует несколько решений (ни одно из них не является идеальным)

1. Используйте Kaazing.

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

2. Объединение js.io и APE (Ajax Push Engine)

APE - это структура комет, но они недавно начали поддерживать Websockets. На их веб-сайте (раздел «APE как прокси») они говорят, что он может запускать js.io библиотеки, которые включают xmpp.js, поэтому их объединение может работать.

3. Используйте Caucho

Это рамка на основе Java, похожая на APE, которая обеспечивает одну остановку в магазине Comet решения, и они, похоже, поддерживают как XMPP и WebSockets

4. Попросите команду Strophe поддержать WebSocket.

Strophe выполняет XMPP через BOSH (двунаправленные потоки через синхронный HTTP), но существует также обсуждение поддержки WebSockets .

Джек Моффитт (основной разработчик и автор упомянутой выше книги), похоже, заинтересован в WebSockets, но нам нужно дать более убедительные рассуждения о том, почему они должны поддерживать WebSocket по BOSH. Если у вас есть хорошие ответы, пожалуйста, присоединяйтесь к протектору.

Я только что попробовал их пример xmpp, bosh, strophe echobot , который хорошо сработал. Вы также можете попробовать его, чтобы посмотреть, соответствует ли он вашим требованиям или нет.

Для # 2 и # 3, они говорят, что они оба поддерживают xmpp и веб-сайты, но не уверены, если они работают вместе.

Для какого приложения вы думаете об использовании XMPP и WebSockets?

Ниже приводятся предложения по альтернативным вариантам.

  • Если вы хотите иметь эквивалентную функциональность для присутствия, чата, чата, вы можете создать Wave Gadget или Robot, а затем выставить их снаружи с помощью Wave Embed API (мертвая ссылка, сохраненная в исторических целях). Волна фактически построена поверх XMPP.
  • Если вы просто ищете возможность передачи сообщений с очень низкой задержкой, вы можете попробовать AMQP .
  • Если вы ищете гораздо более простую потоковую передачу сообщений, вы можете просто передать файл unix, как я показал здесь .

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

-121--1305516-

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

И я хочу использовать $! --- & при вызове методов! Разберись. Если вы собираетесь написать код C++, придерживайтесь условных обозначений C++. И очень важным соглашением C++ является предпочтение функций, не являющихся членами, когда это возможно.

Существует причина, по которой гуру C++ рекомендуют это:

Это улучшает инкапсуляцию, расширяемость и повторное использование. ( std::сортировка может работать со всеми парами итераторов , поскольку не является членом ни одного класса итераторов или контейнеров. И как бы вы ни расширяли std:: Последовательностью , вы не можете ломать его, пока придерживаетесь не-членских функций. И даже если у вас нет доступа к исходному коду класса или нет разрешения на его изменение, вы все равно можете расширить его, определив функции, не являющиеся членами класса)

Лично я не вижу точки в вашем коде. Разве это не намного проще, удобнее для чтения и короче?

string OperateOnString( float num, string a, string b )
{
    string nameS;
    Format(nameS, "%f-%s-%s", num, a.c_str(), b.c_str() );
    return nameS;
}

// or even better, if `Format` is made to return the string it creates, instead of taking it as a parameter
string OperateOnString( float num, string a, string b )
{
    return Format("%f-%s-%s", num, a.c_str(), b.c_str() );
}

Когда в Риме, делайте как римляне, как говорится. Особенно , когда у римлян есть веские причины поступать так, как у них есть. И особенно когда ваш собственный способ сделать это на самом деле не имеет ни одного преимущества. Он более подвержен ошибкам, сбивает с толку людей, читающих ваш код, не является идиоматическим, и это просто больше строк кода, чтобы сделать то же самое.

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

-121--3765849-

Модуль F # Seq определяет парную функцию над IEnumerable < T > , но эта функция отсутствует в рамку .NET.

Если бы он уже был в .Рамка, вместо возврата пар он, вероятно, принял бы функцию селектора из-за отсутствия поддержки кортежей на языках, таких как C # и VB.

var pairs = ns.Pairwise( (a, b) => new { First = a, Second = b };

Я не думаю, что какие-либо из ответов здесь действительно улучшить на ваш простой итератор реализации, которая казалась наиболее естественным для меня (и плакат dahlbyk по взглядам вещей!) тоже.

0
ответ дан 7 November 2019 в 13:06
поделиться

Примерно так:

public static IEnumerable<TResult> Pairwise<T, TResult>(this IEnumerable<T> enumerable, Func<T, T, TResult> selector)
{
    var previous = enumerable.First();
    foreach (var item in enumerable.Skip(1))
    {
        yield return selector(previous, item);
        previous = item;
    }
}
1
ответ дан 7 November 2019 в 13:06
поделиться

В .NET 4 это становится еще проще: -

var input = new[] { "a", "b", "c", "d", "e", "f" };
var result = input.Zip(input.Skip(1), (a, b) => Tuple.Create(a, b));
50
ответ дан 7 November 2019 в 13:06
поделиться

Подробно останавливание предыдущий ответ для предотвращения O (n <глоток> 2 ) приближается путем явного использования переданного итератора:

public static IEnumerable<IEnumerable<T>> Tuples<T>(this IEnumerable<T> input, int groupCount) {
  if (null == input) throw new ArgumentException("input");
  if (groupCount < 1) throw new ArgumentException("groupCount");

  var e = input.GetEnumerator();

  bool done = false;
  while (!done) {
    var l = new List<T>();
    for (var n = 0; n < groupCount; ++n) {
      if (!e.MoveNext()) {
        if (n != 0) {
          yield return l;
        }
        yield break;
      }
      l.Add(e.Current);
    }
    yield return l;
  }
}

Для C# 2, перед дополнительными методами, отбрасывают "это" от входного параметра и вызова как статический метод.

2
ответ дан Community 7 November 2019 в 23:06
поделиться

Решение C# 3.0 (извините:)

public static IEnumerable<IEnumerable<T>> Tuples<T>(this IEnumerable<T> sequence, int nTuple)
{
    if(nTuple <= 0) throw new ArgumentOutOfRangeException("nTuple");

    for(int i = 0; i <= sequence.Count() - nTuple; i++)
        yield return sequence.Skip(i).Take(nTuple);
}

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

Действительно, единственная вещь, делающая это, решением C# 3.0 является.Skip. Возьмите конструкцию, поэтому если Вы просто изменяете это на добавление элементов в том диапазоне к списку вместо этого, это должно быть золотым для 2,0. Тем не менее это все еще не производительно.

1
ответ дан mqp 7 November 2019 в 23:06
поделиться

Альтернатива Pairs реализация, с помощью последней пары, которая сохранит предыдущее значение:

static IEnumerable<Pair<T, T>> Pairs( IEnumerable<T> collection ) {
  Pair<T, T> pair = null;
  foreach( T item in collection ) {
    if( pair == null )
      pair = Pair.Create( default( T ), item );
    else
      yield return pair = Pair.Create( pair.Second, item );
  }
}

Простой Window реализация (только безопасный для личного пользования, если вызывающая сторона не сохраняет возвращенные массивы; см. примечание):

static IEnumerable<T[]> Window( IEnumerable<T> collection, int windowSize ) {
  if( windowSize < 1 )
    yield break;

  int index = 0;
  T[] window = new T[windowSize];
  foreach( var item in collection ) {
    bool initializing = index < windowSize;

    // Shift initialized window to accomodate new item.
    if( !initializing )
      Array.Copy( window, 1, window, 0, windowSize - 1 );

    // Add current item to window.
    int itemIndex = initializing ? index : windowSize - 1;
    window[itemIndex] = item;

    index++;
    bool initialized = index >= windowSize;
    if( initialized )
      //NOTE: For public API, should return array copy to prevent 
      // modifcation by user, or use a different type for the window.
      yield return window;
  }
}

использование В качестве примера:

for( int i = 0; i <= items.Length; ++i ) {
  Console.WriteLine( "Window size {0}:", i );
  foreach( string[] window in IterTools<string>.Window( items, i ) )
    Console.WriteLine( string.Join( ", ", window ) );
  Console.WriteLine( );
}
0
ответ дан Emperor XLII 7 November 2019 в 23:06
поделиться
Другие вопросы по тегам:

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