質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

Q&A

解決済

2回答

423閲覧

指定している文字列と前方一致しており、なおかつ単語が一つ追加されている別の文字列を取得したい

P_036

総合スコア3

Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

0グッド

1クリップ

投稿2022/12/13 08:00

前提

 指定した文字列と前方一致しており、なおかつ単語が一つ足されている要素を取得したいです。

 「A,B,C」という文字列があるとして、「A,B,C,D」という一つ単語が付け足された文字列を取得したいです(「A,B,C,D,E」以降は不要)。
下記のコードの通り、それ自体は実現できているのですが、大きいデータを扱うとなると二重ループがあまりにも大きくなってしまいます。
そのためできれば二重ループを使用せずに、リストから直接ほしい文字列を取得できる方法を探しているのですが、良い改善方法はありますでしょうか? ご助言をしていただければ幸いです。

Python

1  2 sentence=["私,は", "私,は,学生", "私,は,学生,です", 3 "私,は","私,は,私", "私,は,私,に","私,は,私,に,ご褒美","私,は,私,に,ご褒美,を","私,は,私,に,ご褒美,を,あげ","私,は,私,に,ご褒美,を,あげ,ま","私,は,私,に,ご褒美,を,あげ,ま,した"] 4#要素内の単語同士は「,」で結合されています。 5#実際に扱っているsentenceは50万要素以上あります 6 7#文字列alphaが前方一致しており、単語が一つ足されているものをbetaとする 8#betaを最大で3つまで取得したら、次のalphaに移行する 9#完全一致の文字列は除外 10 11 for word_alpha in sentence: 12 13 beta_candidate=[] #beta候補取得 14 15 alpha_length=len(word_alpha.split(",")) 16 17 #文字列alphaに対応するbetaを取得。3回取得 18 19 for word_beta in sentence: 20 if len(beta_candidate)<3: #betaを3回取得できるまでループ 21 beta_length=len(word_beta.split(",")) #単語列の長さを取得 22                23              #前方一致&文字列alphaよりちょうど単語一個分多かったらTrue 24 if word_beta.startswith(word_alpha) and (beta_length==alpha_length+1): 25 beta_candidate.append(word_beta) 26 27 if word_alpha in beta_candidate: #alphaとbetaが完全一致のものは除外 28 beta_candidate.remove(word_beta) 29 30  print(word_alpha,beta_candidate)

補足情報(FW/ツールのバージョンなど)

Goggle の Colabを利用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

指定した文字列と前方一致しており、なおかつ単語が一つ足されている要素

をいいかえると「指定した文字列」(src)と「末尾の単語をひとつ除いたもの」(key)が完全一致した要素がbetaの候補となるかと思います。
よってsrcとkeyを左結合するとbetaの候補が見つかり、それらからsrc毎に先頭3個のみ抽出すればよいでしょう。
これらをpandasで実装したコードは以下のようになります。

Python

1 2import pandas as pd 3pd.set_option('display.unicode.east_asian_width', True) 4 5sentence=["私,は", "私,は,学生", "私,は,学生,です", 6 "私,は","私,は,私", "私,は,私,に","私,は,私,に,ご褒美","私,は,私,に,ご褒美,を","私,は,私,に,ご褒美,を,あげ","私,は,私,に,ご褒美,を,あげ,ま","私,は,私,に,ご褒美,を,あげ,ま,した"] 7 8# 処理用のデータフレーム 9data = [[tuple(s.split(',')), i] for i,s in enumerate(sentence)] 10df = pd.DataFrame(data, columns=['src','idx']) # 分割済み単語のタプルと元配列位置 11df['key'] = df['src'].apply(lambda e:e[:-1]) # 検索用のキー=末尾の単語を除いたもの 12 13# 結合用の列値をタプルからID(数値)に最適化 14dic = {e:i for i,e in enumerate(set(df['src']) | set(df['key']))} 15df['src'] = df['src'].apply(dic.get) 16df['key'] = df['key'].apply(dic.get) 17 18# 左結合 19dfm = df.merge(df, left_on='src', right_on='key', how='left') 20 21# 結合分から元文字列でグループ化して、検索結果の先頭3行のみを残す 22dfm = dfm.dropna()[['idx_x', 'idx_y']] # 見つからなかったものは除く 23dfm = dfm.sort_values(['idx_x', 'idx_y']) 24dfm = dfm.groupby('idx_x').head(3).reset_index(drop=True) 25dfm['idx_y'] = dfm['idx_y'].astype(int) 26print(dfm) 27""" 28 idx_x idx_y 290 0 1 301 0 4 312 1 2 323 3 1 334 3 4 345 4 5 356 5 6 367 6 7 378 7 8 389 8 9 3910 9 10 40""" 41 42# 配列位置→文字列に戻す 43dfm['src'] = dfm['idx_x'].apply(lambda e:sentence[e]) 44dfm['dst'] = dfm['idx_y'].apply(lambda e:sentence[e]) 45print(dfm) 46""" 47 idx_x idx_y src dst 480 0 1 私,は 私,は,学生 491 0 4 私,は 私,は,私 502 1 2 私,は,学生 私,は,学生,です 513 3 1 私,は 私,は,学生 524 3 4 私,は 私,は,私 535 4 5 私,は,私 私,は,私,に 546 5 6 私,は,私,に 私,は,私,に,ご褒美 557 6 7 私,は,私,に,ご褒美 私,は,私,に,ご褒美,を 568 7 8 私,は,私,に,ご褒美,を 私,は,私,に,ご褒美,を,あげ 579 8 9 私,は,私,に,ご褒美,を,あげ 私,は,私,に,ご褒美,を,あげ,ま 5810 9 10 私,は,私,に,ご褒美,を,あげ,ま 私,は,私,に,ご褒美,を,あげ,ま,した 59"""

投稿2022/12/14 04:57

編集2022/12/14 05:14
can110

総合スコア38268

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

P_036

2022/12/20 07:59

回答ありがどうございます! なるほど、pandasで処理を行う方法もあったんですね…… 他の部分で活用してみようと思います! ありがとうございました!!
guest

0

ベストアンサー

python

1sentence=[ 2 "私,は", "私,は,学生", "私,は,学生,です", 3 "私,は","私,は,私", "私,は,私,に","私,は,私,に,ご褒美", 4 "私,は,私,に,ご褒美,を","私,は,私,に,ご褒美,を,あげ", 5 "私,は,私,に,ご褒美,を,あげ,ま","私,は,私,に,ご褒美,を,あげ,ま,した"] 6 7for word_alpha in sentence: 8 l = len(word_alpha.split(',')) + 1 9 beta_candidate = [*filter(lambda x: x.startswith(word_alpha) and len(x.split(',')) == l, sentence)] 10 print(word_alpha, beta_candidate) 11 12# 私,は ['私,は,学生', '私,は,私'] 13# 私,は,学生 ['私,は,学生,です'] 14# 私,は,学生,です [] 15# 私,は ['私,は,学生', '私,は,私'] 16# 私,は,私 ['私,は,私,に'] 17# 私,は,私,に ['私,は,私,に,ご褒美'] 18# 私,は,私,に,ご褒美 ['私,は,私,に,ご褒美,を'] 19# 私,は,私,に,ご褒美,を ['私,は,私,に,ご褒美,を,あげ'] 20# 私,は,私,に,ご褒美,を,あげ ['私,は,私,に,ご褒美,を,あげ,ま'] 21# 私,は,私,に,ご褒美,を,あげ,ま ['私,は,私,に,ご褒美,を,あげ,ま,した'] 22# 私,は,私,に,ご褒美,を,あげ,ま,した []

投稿2022/12/13 08:17

melian

総合スコア19849

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

P_036

2022/12/20 07:57

回答していただきありがとうございます! 無事処理のスピードを上げることができました! まさにフィルターのようなものを欲していたのですが、自力ではたどり着くことができず……本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問