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

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

新規登録して質問してみよう
ただいま回答率
85.48%
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

9回答

2966閲覧

Pythonのfor文が思い通りに動かない

Terratale

総合スコア21

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/09/04 09:41

前提・実現したいこと

例えば下のようなtxtファイルがあったとして

1 2 3 4 5 6 7 8

このファイルを読み込み、
それを、「1,2,3」と3行進んだら1行戻り、また3行「2,3,4」。また1戻って3行分進んで「3,4,5」、、、、
となるように処理をして、

1 2 3 #3行分進んだので次は一つ前に戻る 2 3 4 #3行分進んだので次は一つ前に戻る 3 4 5 #3行分進んだので次は一つ前に戻る 4 5 6 #3行分進んだので次は一つ前に戻る 5 6 7 #3行分進んだので次は一つ前に戻る 6 7 8

処理したものを別のtxtファイルに書き出す。というような動きをするプログラムをPythonで作ろうとしています。

発生している問題・エラーメッセージ

そこで、主な処理をどう記述すれば良いか試すために、以下のようなプログラムを作成しました。

Python2

1# coding: UTF-8 2 3list1 = ['あ','い','う','え','お','か','き','く'] #元のリスト 4length = len(list1) #リストのサイズ 5 6for n in range(length): 7 if n%3 != 0: #3の倍数でなければ 8 print(list1[n]) 9 else: #3の倍数なら 10 print(list1[n]) 11 n = n-2 #繰り返し時に+1されることを考慮し2引いておく

しかし、このプログラムを実行すると出力は以下のようになり、

あ い う え お か き く

思いどおりに動きませんでした。
と、ここで思ったのですが、
nが3の倍数の時は-2するというようなやり方では、nは3以上の数に行けなくなり、実現したい動きどころか、そもそも無限ループしてしまう気がします。
にもかかわらず、実行結果では「あ」から「く」まで出力されており、nがリストの長さまで辿りついて処理が終わっています。

どのようにプログラムを書けば期待通りの動きをさせることができるのでしょうか。
簡単なところで思い違いをして的外れなことを言っている部分があるかもしれませんが、ご教示お願い致します。

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

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

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

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

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

guest

回答9

0

英語でpython sliding window で検索すると色々でてくる話ですね。
Pythonの公式ドキュメントのitertoolsのレシピのpairwise関数も参考になります(2個の場合の正解です)。

pairwiseを2個限定からn個に拡張すると

Python

1from itertools import tee 2 3def window(seq, n): 4 cursors = tee(iter(seq), n) 5 6 for i in range(1, n): 7 for cursor in cursors[i:]: 8 next(cursor, None) 9 10 return zip(*cursors)

となって、実行結果は、

>>> for x in window(range(8),3): ... print(x) ... (0, 1, 2) (1, 2, 3) (2, 3, 4) (3, 4, 5) (4, 5, 6) (5, 6, 7)

となります。

同じくitertoolsのchainと組み合わせて、

from itertools import chain for x in chain.from_iterable(window(range(8),3)): print(x)

0 1 2 1 2 3 2 3 4 3 4 5 4 5 6 5 6 7

となります。

これは、リストである必要がなく、ファイル読み込みのようなシーケンスが対象でも十全に動きます(n行分のメモリしか使いません)。
何十GBもあるようなファイルを相手にする場合の話ということで。

投稿2018/09/04 12:22

編集2018/09/04 14:30
quickquip

総合スコア11038

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

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

0

それを、「1,2,3」と3行進んだら1行戻り、また3行「2,3,4」。また1戻って3行分進んで「3,4,5」、、、、

これを表示するだけならば、以下のようにするとできます。

python

1for i in range(6): 2 for j in range(i,3 + i): 3 print(str(j) + " ",end = "") 4 print();

<実行例>

0 1 2 1 2 3 2 3 4 3 4 5 4 5 6 5 6 7

これを用いて、変数jをlist1の番号に当てはめれば以下のように表示することができます。

python

1list1 = ['あ','い','う','え','お','か','き','く'] 2num = 3 3for i in range(len(list1) - num): 4 for j in range(i,num + i): 5 print(str(list1[j]) + " ",end = "") 6 print();

<実行例>

あ い う い う え う え お え お か お か き

投稿2018/09/04 09:55

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Terratale

2018/09/04 11:40

回答ありがとうございました。 二重for文という手もあるんですね。 参考になりました!
退会済みユーザー

退会済みユーザー

2018/09/04 12:05

実装方法はともかく、発想はこれが一番シンプルなんじゃないかなぁ。 実際の利用はファイルってところが、悩ましいけど^^;
guest

0

質問文を見たとき自然に思いついたのはこの実装でしたが、素直にwhileで書いた方が良いかもしれません。

python

1list1 = [1,2,3,4,5,6,7,8] 2stack = list1[:] 3flag = 0 4while stack: 5 if flag == 0: 6 print(stack.pop(0), "# 最初or戻った時") 7 flag = 1 8 elif flag == 1: 9 a = stack.pop(0) 10 print(a) 11 flag = 2 12 elif flag == 2: 13 b = stack.pop(0) 14 print(b) 15 stack.insert(0, b) 16 stack.insert(0, a) 17 flag = 0 18 else: 19 print("") 20 21""" => 221 # 最初or戻った時 232 243 252 # 最初or戻った時 263 274 283 # 最初or戻った時 294 305 314 # 最初or戻った時 325 336 345 # 最初or戻った時 356 367 376 # 最初or戻った時 387 398 407 # 最初or戻った時 418 42""" 43# 質問文の出力例は一番最後の戻りがないけど、それで良いのだろうか

投稿2018/09/04 10:58

編集2018/09/04 10:59
hayataka2049

総合スコア30933

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

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

Terratale

2018/09/04 11:35

なるほど! While文を使うという方法がありましたね! 頭が凝り固まってました。 回答ありがとうございます。
hayataka2049

2018/09/04 12:00

すみません、「whileでインデックスループにして」と書くべきでした 私の回答はプッシュダウン・オートマトン風実装ですが、これにはメリットはないです
guest

0

このプログラムを実行すると出力は以下のようになり、
...略...
思いどおりに動きませんでした。

アイデア自体は悪くないですが、残念ながらループ内でカウンタを置き換えても無意味なのです。

for文ではターゲット(今回は変数n)に対して毎周代入が発生します。
ループ内でどんなにnの値をいじっても、次の一周が始まる際に上書きされてしまいます。


要素をずらしてzipしてみるのも良いでしょう。

Python

1it = range(1, 9) 2for elems in zip(it, it[1:], it[2:]): 3 print(*elems, sep='\n')

実行結果 Wandbox

1 2 3 2 3 4 3 4 5 4 5 6 5 6 7 6 7 8

これがファイルの読み込みに転用できるかは疑問ですが。

投稿2018/09/04 10:17

編集2018/09/04 10:28
LouiS0616

総合スコア35660

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

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

Terratale

2018/09/04 11:36

回答ありがとうございます。 ループ内でnをいじっても意味がない理由が理解できました!
guest

0

ベストアンサー

3文字ごとに2文字戻るのを実装すれば良いです
while文なら

python

1list1 = ['あ','い','う','え','お','か','き','く'] #元のリスト 2length = len(list1) #リストのサイズ 3 4idx = 0 # 表示する位置 5count = 0 # 表示した文字数をカウント 6 7while idx < length: 8 print(list1[idx]) 9 idx += 1 10 count += 1 11 if count % 3 == 0: # 3文字目のとき 12 if idx == length: # 最後の1文字なら戻らないのでbreak(?) 13 break 14 idx -= 2 # 次の表示位置を変更 15

実行例

あ い う い う え う え お え お か お か き か き く

投稿2018/09/04 10:03

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Terratale

2018/09/04 11:44

回答ありがとうございました! プログラム内のコメントもついてて分かりやすかったです!
guest

0

for n in range(length):

では、ループ内で n を変更してもダメです
それするなら、while 文で実装しょう

投稿2018/09/04 09:55

y_waiwai

総合スコア87747

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

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

Terratale

2018/09/04 11:41

なるほど! While文の存在すっかり忘れてました! 回答ありがとうございました!
guest

0

ファイルから読み込むバージョンを書いてみました。
LineReader というクラスを定義しました。 これは 3行分のバッファをもたせ、3 行分なら すでに読んだ行読まなかったことにできるようにしました。
ただし質問文にある表示例とは 少し違う動作をします。質問文の場合は、8 を表示したらすぐに終了してます。
でもここに書いたコードでは、8 を読んだあとも ungetline ができるので、すこし多く行が評されます。
(ファイルの末尾に達したときの処理を変更すれば、質問文と同じ表示にできrとおもいます。試してみてください)
ungetline.py

class LineReader: def open(self, file_path): self.file = open(file_path, "r") self.lines = [] self.pointer = 0 self.max_size = 3 def close(self): self.file.close() self.lines = [] self.pointer = 0 def getline(self): line = None if 0 <= self.pointer and self.pointer < len(self.lines): line = self.lines[self.pointer] self.pointer += 1 return line line = self.file.readline() if not line: return line line = line.rstrip("\n") if len(self.lines) >= self.max_size: self.lines.pop(0) self.lines.append(line) self.pointer = len(self.lines) return line def ungetline(self): if 1 <= self.pointer and self.pointer <= len(self.lines) + 1: self.pointer -= 1 return self.lines[self.pointer] return None reader = LineReader() reader.open("data.txt") counter = 0 while True: line = reader.getline() if not line: break print(line) counter += 1 if counter % 3 == 0: reader.ungetline() reader.ungetline() reader.close()

実行例:
イメージ説明

投稿2018/09/04 14:55

katoy

総合スコア22324

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

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

0

ファイル操作への転用を意識して作ってみました。

python

1list1 = ['あ','い','う','え','お','か','き','く'] 2tmp_list = [] 3rows = 3 - 1 4for i in range(len(list1)): 5 tmp_list.append(list1[i]) 6 if i < rows: 7 continue 8 print(','.join(tmp_list)) 9 tmp_list.pop(0)

投稿2018/09/04 12:36

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

すみません間違えました

投稿2018/09/04 11:58

編集2018/09/04 11:59
yo-da

総合スコア8

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問