2016-07-07 10 views
1

トークン化関数の値のベクトルがtokenize()であるとします。私はそれが2つの値しか持たないことを知っています。最初の値をaに、2番目の値をbに保存します。 Pythonでは、私はどうなる:ベクトルを値に分割する

a, b = string.split(' ') 

私が醜い方法でそのようにそれを行うことができます:

vector<string> tokens = tokenize(string); 
string a = tokens[0]; 
string b = tokens[1]; 

しかし、それはコード、余分な変数、および以下可読性の2本の余分なラインを必要とします。

どのように私はC++でこのようなことをきれいで効率的なやり方でやっていますか?

EDIT:私は、効率が非常に重要であることを強調しなければなりません。あまりにも多くの答えがこれを満たさない。これにはmy tokenization functionの変更が含まれます。

EDIT 2:私はコントロール外の理由でC++ 11を使用していますが、Boostも使用できません。

as_tuple<N>vector<string>への変換をいくつかに-宣言する機能です
auto [a,b] = as_tuple<2>(tokenize(str)); 

:構造化されたバインディングを持つ

+2

トークンの代わりにC++の方法で繰り返します – BeyelerStudios

+7

世界が本当に虹と蝶ですが、それに2つの値しか持たないことがわかっているのなら、なぜ一般的に使われているコンテナを返す関数を使っていますか?任意の長さの結果セットの?あなたの2つの 'std :: string'オブジェクトを宣言し、それを単に(文字列のペアを取得する)' tokenize_pair() '関数に渡して、パラメータを参照し、それを良いものと呼んでください。 – WhozCraig

+0

@WhozCraigこのような機能の実装方法はわかりません。私はPythonの背景から来ています。このような機能は非常に便利です。 –

答えて

2

あなたは、あなたのような何かを書くことができ、「それが唯一の2つの値を持つことになります知っている」場合:

#include <cassert> 
#include <iostream> 
#include <string> 
#include <tuple> 

std::pair<std::string, std::string> tokenize(const std::string &text) 
{ 
    const auto pos(text.find(' ')); 
    assert(pos != std::string::npos); 

    return {text.substr(0, pos), text.substr(pos + 1)}; 
} 

あなたcodeは、STLの力の偉大な例ですが、それはおそらく少し遅くなります。

int main() 
{ 
    std::string a, b; 

    std::tie(a, b) = tokenize("first second"); 

    std::cout << a << " " << b << '\n'; 
} 

残念ながらなしstructured bindings(C++ 17)あなたはstd::tieハックと変数を使用する必要がabが存在しなければなりません。

+0

@asimesよりもはるかに速く、私のコードではそうです。アップヴォートを持っていれば誰でもあなたを受け入れることができますか?) –

+0

@uoɥʇʎPʎzɐɹC、彼の 'tokenize'関数が効率的であるため、実装より速いです。私は 'tokenize'関数を書いていませんでした。関数から2つの変数を一度に割り当てる方法を示しました – asimes

+0

' -O0'か '-O3'のどちらであっても(どちらも' -O3'ではるかに高速ですが)、あなたのコードは6-7倍速く –

3

(間違いなくC++ 17になります)、あなたのような何かを書くことができると思いますtuple<string, string, ... N times ...>、おそらくサイズが一致しない場合は投げます。 std::vectorはコンパイル時にサイズがわからないので、破棄することはできません。これは必然的にstringの余分な動きをするので、コードの明瞭さを得るために効率を失うことになります。多分それは大丈夫です。

tokenize<N>と書いて、余分な移動を避けてtuple<string, string, ... N times ...>を直接返すかもしれません。その場合:

auto [a, b] = tokenize<2>(str); 

は素晴らしいです。


あなたが持っているものは、できることです。しかし、あなたの変数を参照するだけです。

std::vector<std::string> tokens = tokenize(str); 
std::string& a = tokens[0]; 
std::string& b = tokens[1]; 

ええと、それは余分なコード行です。それは世界の終わりではありません。理解しやすいです。

std::pair<std::string, std::string> tokenize(const std::string& str); 

それとも、パラメータとして関数に文字列を空にするために2つの参照を渡すことになります。それは、文字列のペアではなく、ベクトルを返すように

+0

文字列をスペースに分割する 'tokenize_pair()'関数を実装してもらえますか?私は他のデリミタを必要とせず、パフォーマンスはキー*です。 –

+0

@uoɥʇʎPʎzɐɹCこれは実際にこのサイトの仕組みではありません。 – Barry

+0

私は十分に長くここにいました。あなたの答えは決して質問に答えるものではありません。あなたはパフォーマンスの代わりに美しさに出かけました。 –

0

理想的には、tokenize()機能を書き換えると思います。

void tokenize(const std::string& str, std::string& result_1, std::string& result_2); 

tokenize関数を制御できない場合は、文字列をベクトルから最適な方法で移動するのが最適です。

std::vector<std::string> tokens = tokenize(str); 
std::string a = std::move(tokens.first()); 
std::string b = std::move(tokens.last()); 
関連する問題