Перечисление по кратному выражению

Используйте Параметры останова для представления неопределенного числа аргументов в качестве массива.

function sumTwoSmallestNumbers(...numbers) {
  const filter = numbers.filter(x => x > -1).sort((a, b) => a - b);
  return filter[0] + filter[1];
}

console.log(sumTwoSmallestNumbers(544, 32654, 34297, 9237, 343, 98));

5
задан Barry 19 January 2019 в 17:10
поделиться

2 ответа

Крайне важно, чтобы сгенерированный код был максимально эффективным.

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

Есть ли способ сделать это, избегая как переменных времени выполнения, так и вспомогательной функции?

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

static_assert(__cplusplus >= 201703L, "example written for C++17 or later");

#include <cstddef>

#include <array>
#include <type_traits>
#include <utility>

namespace detail {

template<std::size_t... inds, class F>
constexpr void gen_inds_impl(std::index_sequence<inds...>, F&& f) {
  f(std::integral_constant<std::size_t, inds>{}...);
}

}// detail

template<std::size_t N, class F>
constexpr void gen_inds(F&& f) {
  detail::gen_inds_impl(std::make_index_sequence<N>{}, std::forward<F>(f));
}

// the code above is reusable

template<
  std::size_t... inds_out,
  class T, std::size_t size_out, std::size_t size_in
>
constexpr std::array<T, size_out> insert1(
  std::array<T, size_out> out,
  std::array<T, size_in> in
) {
  static_assert((... && (inds_out < size_out)));
  static_assert(sizeof...(inds_out) <= size_in);

  gen_inds<sizeof...(inds_out)>([&] (auto... inds_in) {
    ((out[inds_out] = in[inds_in]), ...);
  });

  return out;
}

Аналогичной альтернативой является static_for подход:

static_assert(__cplusplus >= 201703L, "example written for C++17 or later");

#include <cstddef>

#include <array>
#include <type_traits>
#include <utility>

namespace detail {

template<std::size_t... inds, class F>
constexpr void static_for_impl(std::index_sequence<inds...>, F&& f) {
  (f(std::integral_constant<std::size_t, inds>{}), ...);
}

}// detail

template<std::size_t N, class F>
constexpr void static_for(F&& f) {
  detail::static_for_impl(std::make_index_sequence<N>{}, std::forward<F>(f));
}

// the code above is reusable

template<
  std::size_t... inds_out,
  class T, std::size_t size_out, std::size_t size_in
>
constexpr std::array<T, size_out> insert2(
  std::array<T, size_out> out,
  std::array<T, size_in> in
) {
  static_assert(sizeof...(inds_out) >= 1);

  static_assert((... && (inds_out < size_out)));
  static_assert(sizeof...(inds_out) <= size_in);

  constexpr std::size_t N = sizeof...(inds_out);

  static_for<N>([&] (auto n) {
    // note the constexpr
    constexpr std::size_t ind_out = std::array{inds_out...}[n];
    constexpr std::size_t ind_in = n;
    out[ind_out] = in[ind_in];
  });

  return out;
}
0
ответ дан Julius 19 January 2019 в 17:10
поделиться

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

И мне очень нравится ваше второе решение, но ... как насчет использования итераторов для y (если y поддерживает cbegin() и итераторы, очевидно).

Что-то как (осторожно: код не проверен)

template <std::size_t Ii...., std::size_t Xsize, std::size_t Ysize>
constexpr container<Xsize> insert(container<Xsize> x, container<Ysize> const & y) {
   auto it = y.cbegin();
   ((x[Ii] = *it++), ...);
   return x;
}

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

Но я также полагаю, что с хорошим оптимизатором заметной разницы нет.

0
ответ дан max66 19 January 2019 в 17:10
поделиться
Другие вопросы по тегам:

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