Chcę utworzyć funkcję, w której mogę iterować po tablicy / wektorze zawierającym zmienną liczbę ciągów i muszę znać długość ciągów, zanim wyślę je do funkcji. Jak mogę to osiągnąć w efektywny sposób?

Mam trochę luźne pojęcie o tej funkcji, ale jak mogę wydajnie wysłać do niej tablicę / wektor ciągów i rozmiar wszystkich tych ciągów łącznie. Na przykład funkcja mogłaby wyglądać mniej więcej tak:

myFunc(vector<string> s, int totalWordLength) {
    // Loop over strings in vector.
}

Mógłbym zrobić coś takiego, aby stworzyć wektor ciągów.

const char *args[] = {"12345", "678"};
vector<string> s(args, end(args));

Ale jak mam wtedy sprawdzić rozmiar ciągów (8) w tym bez zapętlania go, aby móc wysłać go do myFunc(s, sizeOfStrings)?

Jeśli masz pomysł, aby osiągnąć ten sam wynik, używając zamiast niej tablicy lub czegoś podobnego, daj mi znać. Staram się to robić tak wydajnie, jak to tylko możliwe.

1
Yahboysurge 31 marzec 2020, 22:23

3 odpowiedzi

Najlepsza odpowiedź

Iteruj po kontenerze (klasa kontenera nie ma znaczenia)

const char *args[] = {"12345", "678"};
vector<string> s(args, end(args));

size_t sizOfS = 0;
for( auto& item : s )
  sizOfS += item.length();

Inny sposób łączy proces wypełniania tablicy i obliczania długości:

const char *args[] = {"12345", "678"};
std::vector<std::string> s;
s.reserve(sizeof(args)/sizeof(args[0]));

size_t sizOfS = 0;
for( const std::string& item : args )
{
  sizOfS += item.length();
  s.push_back(item);
}

Niezależnie od tego, co zrobisz, koszt procesu wyniesie O (n), gdzie n = strings * their-total-length. Nie ma innego zdefiniowanego sposobu, ale kilka funkcji, które mogą zmienić pętlę w jedną linijkę. Nawet jeśli zdefiniujesz własny kontener, który będzie śledził długość ciągów, jego koszt będzie miał tę samą kolejność.

To, którego kontenera użyć, zależy od rodzaju działań, jakie zamierzasz wykonać, wektor miał stały koszt losowego dostępu do elementów kontenera, ale liniowo zwiększał się koszt zwiększania jego przechowywania. lista może mieć tani koszt wstawienia \ wypychania, ale ma sekwencyjny iterator.

1
Swift - Friday Pie 31 marzec 2020, 19:48

Biorąc pod uwagę twój scenariusz, podejściem mogłoby polegać na obliczeniu długości łańcuchów w czasie konstruowania wektora.

Jednym z rozwiązań wykorzystujących szablon wariadyczny może być opakowanie takie jak to (na żywo):

#include <iostream>
#include <vector>
#include <string>

struct V
{
    template <typename ... T>
    V( T&& ... t ) : v{ std::forward<T>(t)... }
    {
        for ( const auto& s : v ) size += s.size();
    }

    std::vector<std::string> v;
    std::size_t size {0};
};

int main()
{
    const char *args[] = { "12345678", "6789", "1234", "5678" };

    V obj ( std::begin(args), std::end(args) );

    std::cout << "No. of Strings : " << obj.v.size() << '\n';
    std::cout << "Total Length   : " << obj.size << '\n';

    return 0;
}

Wynik:

No. of Strings : 4
Total Length   : 20
0
Azeem 31 marzec 2020, 20:02

Jeśli chcesz poznać długości wszystkich łańcuchów w wektorze i często je odpytywać (nie jest to jednorazowa rzecz), możesz obliczyć długość łańcuchów po ich dodaniu i zapisać sumę razem z wektorem.

Szybki przykład z klasą:

class MyClassFoo {
public:
  std::vector<std::string> items;
  std::size_t total_item_sizes = 0;

  void addItem(const std::string& item) {
    total_item_sizes += item.length(); // Add its length to the total
    items.emplace_back(item); // Add the item to the vector 
  }
}

Następnie możesz przekazać ten obiekt i zapytać go.

Jeśli chcesz być bardziej efektywny, przekaż przez odniesienie lub przenieś parametry jednorazowego użytku. Jest to ważne w przypadku czegoś takiego jak std::vector, ponieważ prawdopodobnie nie chcesz kopiować wszystkich jego elementów.

Poza tym jest mało prawdopodobne, że jest to faktycznie konieczne, chyba że próbujesz zsumować długości wszystkich ciągów bardzo często i jest ich dużo, twoje wąskie gardło nie będzie iterować po {{ X0}}. Twoje zapotrzebowanie na „wydajność” pachnie jak przedwczesna optymalizacja. Zapamiętaj regułę 20-80 (80% czasu wykonywania programu spędza na uruchamianiu 20% kodu).

0
Firefly 31 marzec 2020, 19:43