1016 Stimmen

Verkettung von zwei std::Vektoren

Wie verkette ich zwei std::vector s?

10 Stimmen

Die gegebenen Antworten sind nicht wirklich zusammenhängend. Sie fügen eine Kopie an. Es könnte (aus Gründen der Effizienz) sinnvoll sein, eine std::vector concatenate-Methode zu erstellen, allerdings würde dies eine ausgeklügelte gemeinsame Nutzung der Verwaltung der Knoten erfordern, und das ist wahrscheinlich der Grund, warum dies noch nicht geschehen ist.

16 Stimmen

@FauChristian: Nein, unter Effizienzgesichtspunkten kann es keinen Nutzen geben. Der Vektorspeicher muss kontinuierlich sein, also ist das, was Sie vorschlagen, unmöglich. Wenn Sie "eine ausgeklügelte gemeinsame Nutzung der Verwaltung der Knoten" wollten und die Vektorklasse auf diese Weise ändern würden, würden Sie bei einer Deque landen. Selbst dann ist es sehr schwierig, den Speicher in der vorgeschlagenen Weise wiederzuverwenden, auch wenn es allmählich ein wenig praktikabler wäre. Ich glaube nicht, dass es derzeit implementiert ist. Die Hauptsache ist, dass in einem solchen Sharing von Management-Knoten (eine deque) der Endknoten teilweise leer sein könnte.

18 Stimmen

Bin ich der Einzige, der sich fragt, warum dies nicht als a + b o a.concat(b) in der Standardbibliothek? Vielleicht wäre die Standardimplementierung suboptimal, aber nicht jede Array-Verkettung muss mikro-optimiert sein

4voto

Daniel Punkte 7509

Hier ist eine allgemeine Lösung, die die Move-Semantik von C++11 verwendet:

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
    if (lhs.empty()) return rhs;
    if (rhs.empty()) return lhs;
    std::vector<T> result {};
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.cend(), lhs.cbegin(), lhs.cend());
    result.insert(result.cend(), rhs.cbegin(), rhs.cend());
    return result;
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
    lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
    return std::move(lhs);
}

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
    rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
    return std::move(rhs);
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
    if (lhs.empty()) return std::move(rhs);
    lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
    return std::move(lhs);
}

Beachten Sie, dass dies ein Unterschied ist zu append in eine vector .

0 Stimmen

1. Anruf haben 2. Überlast

3voto

instance Punkte 1368
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));

6 Stimmen

Dieser Codeschnipsel kann das Problem zwar lösen, erklärt aber nicht, warum oder wie er die Frage beantwortet. Bitte fügen Sie eine Erklärung für Ihren Code ein Das trägt wirklich dazu bei, die Qualität Ihres Beitrags zu verbessern. Flaggenleger / Prüfer: Bei reinen Code-Antworten wie dieser sollten Sie eine negative Bewertung abgeben, nicht löschen! (Hinweis: Diese Antwort könnte tatsächlich so einfach sein, dass eine Erklärung und damit eine Herabstufung unnötig ist. Sie sollten dennoch eine Erklärung hinzufügen, um weitere NAA/VLQ-Flags zu vermeiden).

3voto

Vladimir U. Punkte 132

Sie können Ihre eigene Vorlage für + Operator erstellen:

template <typename T> 
inline T operator+(const T & a, const T & b)
{
    T res = a;
    res.insert(res.end(), b.begin(), b.end());
    return res;
}

Als Nächstes: Verwenden Sie einfach +:

vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
    cout << x << " ";
cout << endl;

Dieses Beispiel ergibt eine Ausgabe:

1 2 3 4 5 6 7 8

5 Stimmen

Verwendung von T operator+(const T & a, const T & b) gefährlich ist, ist es besser, die vector<T> operator+(const vector<T> & a, const vector<T> & b) .

3voto

Drew Punkte 10978

Ich habe diese Funktion implementiert, die eine beliebige Anzahl von Containern verkettet, indem sie von rvalue-Referenzen ausgeht und ansonsten kopiert

namespace internal {

// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
    // Currently, require each homogenous inputs. If there is demand, we could probably implement a
    // version that outputs a vector whose value_type is the common_type of all the containers
    // passed to it, and call it ConvertingConcatenate.
    static_assert(
            std::is_same_v<
                    typename std::decay_t<Target>::value_type,
                    typename std::decay_t<Head>::value_type>,
            "Concatenate requires each container passed to it to have the same value_type");
    if constexpr (std::is_lvalue_reference_v<Head>) {
        std::copy(head.begin(), head.end(), std::back_inserter(*target));
    } else {
        std::move(head.begin(), head.end(), std::back_inserter(*target));
    }
    if constexpr (sizeof...(Tail) > 0) {
        AppendNoReserve(target, std::forward<Tail>(tail)...);
    }
}

template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
    if constexpr (sizeof...(Tail) > 0) {
        return head.size() + TotalSize(tail...);
    } else {
        return head.size();
    }
}

}  // namespace internal

/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
    size_t totalSize = internal::TotalSize(head, tail...);
    std::vector<typename std::decay_t<Head>::value_type> result;
    result.reserve(totalSize);
    internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
    return result;
}

3voto

Aroonalok Punkte 492

Für Container, die Folgendes bieten push_back (String, Vektor, Deque, ...):

std::copy(std::begin(input), std::end(input), std::back_inserter(output))

y

für Container, die Folgendes bieten insert (Karten, Sets):

std::copy(std::begin(input), std::end(input), std::inserter(output, output.end()))

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X