Есть ли более эффективный способ сравнения нескольких значений в структуре? [Дубликат]

docker stack logs является фактически запрошенной функцией в запросе issue 31458

для журналов стека докеров, которые могут отображать журналы для стека докеров так же, как docker service logs работают в 1.13. docker-compose работает аналогично сегодня, показывая чередующиеся журналы для всех контейнеров, развернутых из файла компоновки. Это будет полезно для устранения любых ошибок, которые распространяются на гетерогенные сервисы.

blockquote>

Это все еще ожидает, поскольку, поскольку Drew Erny (dperny) подробности:

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

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

blockquote>

11
задан TemplateRex 3 July 2012 в 15:44
поделиться

4 ответа

Я хотел бы сделать все это сам.

Вы должны сравнивать значения Obj::field2, если значения Obj::field1 равны.

Легко понятный способ:

/* This will meet the requirements of Strict-Weak-Ordering */

if (a.field1 != b.field1) return a.field1 < b.field1;
else                      return a.field2 < b.field2;

Правильный (рекомендуемый) способ:

« правильный » способ его использования использует только operator<, чтобы сравнить поля, ниже выглядит более сложным, чем на самом деле.

Однако он даст тот же результат, что и ранее написанный простой для понимания пример.

return a.field1 < b.field1 || (
  !(b.field1 < a.field1) && a.field2 < b.field2
);

Должен быть способ реализации operator<, не вызывая много головной боли?

C ++ 11

Вы можете использовать std::tuple из STL , которые уже имеют operator< для нескольких определенных полей, например, в приведенном ниже примере.

#include <utility>

...

inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
  return std::tie (lhs.field1, lhs.field2) < std::tie (rhs.field1, rhs.field);
}

C ++ 03

Если ваш компилятор еще не поддерживает C ++ 11, и вам нужно сравнить только два поля из каждого объекта, который вы могли бы использовать std::pair.

Причина для std::make_pair - это то же самое как в предыдущем примере, используя std::tie.

#include <utility>

...

inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
  return std::make_pair (lhs.field1, lhs.field2)
       < std::make_pair (rhs.field1, rhs.field2);
}

с использованием std::pair потребует re-копии членов, которые будут созданы, что в некоторых случаях нежелательно.

Это действительно рекомендуемая практика?

См. ниже вопрос / ответы для получения дополнительной информации, но для его суммирования вверх; подход c ++ 11 не вызывает много накладных расходов, и его очень просто реализовать.

28
ответ дан Community 19 August 2018 в 13:54
поделиться
  • 1
    Или return (a.field1 == b.field1) ? a.field2 < b.field2 : a.field1 < b.field1;. – Richard J. Ross III 3 July 2012 в 14:56
  • 2
    Благодарю. Означает ли это, что первая версия является неправильным порядком для ключей на std :: map? (в основном не строгий слабый порядок, приведет к ошибкам во время выполнения) или это просто другой порядок, чем тот, который я намеревался? – lezebulon 3 July 2012 в 14:58
  • 3
    @lezebulon: Это не SWO, см. пример в моем ответе. – Oliver Charlesworth 3 July 2012 в 15:07
  • 4
    @lezebulon. Ваша оригинальная версия не соответствует требованиям для функции заказа, поэтому ваш код имеет неопределенное поведение. Все может случиться, и на самом деле будет много странных вещей. – James Kanze 3 July 2012 в 15:19
  • 5
    "Канонический" способом записи этого условия является return a.field1 < b.field1 || (!(b.field1 < a.field1) && a.field2 < b.field2). Canonical главным образом потому, что он использует только <; на практике я не считаю это понятным и использую его только в контексте шаблона библиотеки (где я не хочу налагать никаких дополнительных ограничений на типы, отличные от тех, которые требуются стандартной библиотекой). – James Kanze 3 July 2012 в 15:23

Нет. Вам нужно также поймать (a.field1 > b.field1).

Это не строгое слабое упорядочение, потому что оно даст (1,2) < (2,1), но также (2,1) < (1,2).

4
ответ дан Oliver Charlesworth 19 August 2018 в 13:54
поделиться

Подумайте, что произойдет, если a.field1 больше, чем b.field1, но a.field2 меньше b.field2. В этом случае вы сравниваете только только на field2, который не то, что вы хотите.

Вы хотите только field2 включить игру, где field1 равно, так что вы ищете что-то вроде (псевдокод):

if a.field1 < b.field1:
    return true

if a.field1 > b.field1:
    return false

# field1 is equal here.

return a.field2 < b.field2

В стороне, я не большой поклонник f11], так как это необязательно и может привести к «отступовному аду»: -)

Я склоняюсь к тому, чтобы превращать такие вещи, как:

if condition:
    return something
else:
    do something else

в:

if condition:
    return something
do something else

, так как я нахожу, что полученный код легче следовать.

Но имейте в виду, что это только личное предпочтение, не стесняйтесь игнорировать его, если хотите.

6
ответ дан paxdiablo 19 August 2018 в 13:54
поделиться

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

template<typename T>
bool operator< (T const& a, T const& b)
{
        return (
                 ( a.field1 < b.field1 ) || (( a.field1 == b.field1 ) &&
                 ( a.field2 < b.field2 ))
        );
}

. Это предполагает, что ваш примитивный тип field1 имеет operator==. Это утомительно вводить это для более чем двух полей, но вы можете использовать std::lexicographical_compare, если ваш класс obj сохраняет поля внутри std::array<T, N> для некоторого типа T и размера N

template<typename T, int N>
struct obj
{
    std::array<T, N> field;
};

bool operator< (obj const& a, T const& b)
{
        return std::lexicographical_compare(
            a.field.begin(), a.field.end(), 
            b.field.begin(), b.field.end()
        );
}

Обратите внимание, что есть проект документа N3326 , который обсуждает автоматически добавление операторов == и < для типов классов.

2
ответ дан TemplateRex 19 August 2018 в 13:54
поделиться
  • 1
    Почему вы избегаете явного ветвления? Я не думаю, что это медленнее, чем логические короткие циклы. – Mooing Duck 6 July 2012 в 18:47
  • 2
    @MooingDuck На самом деле это не проверено, и оно может даже отличаться на платформу. Просто написал это как любопытство. – TemplateRex 6 July 2012 в 19:07
Другие вопросы по тегам:

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