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

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

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

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

Q&A

解決済

6回答

2130閲覧

pythonのrangeの重複部分を計算する方法について

yowayowakun

総合スコア7

Python

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

1グッド

2クリップ

投稿2021/11/23 07:19

Pythonで、2つのrangeの間の重複部分を計算する最も良い方法はどのようなものでしょうか?
例えば、

python

1x = range(2, 11) 2y = range(7, 18)

このような場合には、range(7, 11)または[7, 8, 9, 10]などのような値を計算したいです。
これをPythonで行う場合の最も良い方法としては、どのようなものが考えられるのでしょうか?
ご教示ください。

melian👍を押しています

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

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

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

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

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

ppaul

2021/11/23 07:50

この場合だけを解決すれば良いのですか。 stepが入り、それが負数の場合なども考えなければならないとなると、どういう順序で実行したいのかという仕様が決まっていないと答えが出せません。
yowayowakun

2021/11/23 08:26

すみません、「どういう順序で実行したいのか」というのは、どのような意味でしたでしょうか? と言いますのは、値を計算したいというのが目的でして、順序ということの意味がよくわかりませんでして...
ppaul

2021/11/23 08:58

例えば、range(7)とrange(10,4,-1)の重複部分を実行したいとして、そこで実行する文がprint(i)だったりするとき、 6 5 になるか 5 6 になるかという問題です。
yowayowakun

2021/11/23 10:03

何かを実行するという事ではなくて、値が取得できればよいのですが、もしソートが必要な場合には得られたデータをソートすることで対応できる程度の処理として考えております。
quickquip

2021/11/23 23:25 編集

> 値が取得できればよい えっ? でもその仕様をどうするかが提示されないなら、どのようなコードが適切か(なにが必要十分か、なにで十分か)とか、回答を評価する観点がなくなってしまいますよね。 回答するべきコードの仕様が曖昧でしかないし、そうなら、質問の「rangeの重複部分を計算する」はやりたいことに対して過大すぎる表現だと思います。 rangeのstepが負の場合は考えません、とか、rangeのstepが負の場合はこういう感じで十分です、とかそういうことを、質問に追記・修正してほしいです。(そもそもそういう意図の欄です。ここに情報を書かないで質問に書きましょう)
yowayowakun

2021/11/24 08:21

回答として記載させて頂きましたが、rangeとして定義される要件は、私としては明快であったかなと考えます。stack overflowでは、ほぼ同等の記述の質問で回答が成立していましたし、この質問においても望む回答が得られたものと考えます。 ただ、一部の方には伝わらない部分もあったかと思いますので、万人にわかるような記述でなかった事はお詫びします。申し訳ございませんでした。
guest

回答6

0

Python

1z = range(y.start, x.stop)

yのお尻とxの頭が重なる場合とか、
三つ以上のrangeを扱う場合は集合の方が良いでしょうね。

別解

多少慣れてないと読みづらいかもですが、集合を利用するならこんな感じが簡潔で好みです。

Python

1start, *_, stop = sorted({*x} & {*y}) 2z = range(start, stop)

zがリストで良いなら、単に。

Python

1z = sorted({*x} & {*y})

種明かしを受けて

全体的には、私自身もsetを利用する方法を想定していましたが、とはいえsetにするとメモリを不必要に使ってしまう部分もあるので、その辺のコメントがあったりすると嬉しいなと思っていました。

こんなのはどうでしょう。

Python

1rs = [x, y,] 2z = ( 3 i 4 for i in range( 5 min(e for r in rs for e in (r.start, r.stop)), 6 max(e for r in rs for e in (r.start, r.stop)) 7 ) 8 if all(i in r for r in rs) 9)

これならrangeが何個でも、負のstepであろうと対応できますし、領域も圧迫しません。

投稿2021/11/23 07:35

編集2021/11/24 08:34
LouiS0616

総合スコア35668

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

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

melian

2021/11/23 07:41

上手い!
ikapy

2021/11/23 09:58

太田道灌(同感)
yowayowakun

2021/11/24 15:07

既に高評価をつけていて、これ以上の高評価ができませんが、ありがとうございます!
guest

0

他方が部分集合であるケースも考慮するとHow to find range overlap in python?のAndrew Clarkさんの回答もよさそうです。

Python

1for xs, ys in [((2,11),(7,18)),((1,5),(2,4)),((1,5),(5,10))]: 2 x = range(*xs) 3 y = range(*ys) 4 r = range(max(x[0], y[0]), min(x[-1], y[-1])+1) 5 print(x, y, list(r)) 6 7#range(2, 11) range(7, 18) [7, 8, 9, 10] 8#range(1, 5) range(2, 4) [2, 3] 9#range(1, 5) range(5, 10) []

投稿2021/11/23 08:10

can110

総合スコア38341

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

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

0

リスト内包表記を使うのが一番シンプルかと思います。

python3

1x=range(2,11) 2y=range(7,18) 3print([elem for elem in x if elem in y]) #[7, 8, 9, 10]

この記法ではlistの形式で値が返されるので、rangeオブジェクトに変えたい場合は適宜maxとmin関数で再度作り変えればいいかと思います。

投稿2021/11/23 07:41

Karakuri_Polta

総合スコア50

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

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

quickquip

2021/11/25 02:34

rangeオブジェクトに含まれるかどうかの判定は計算でされているので、 -1 in range(0, 1_000_000_000_000_000_000_000) みたいな判定でもrangeのイテレーションが発生しないんですよね。 だからこれは実質xの長さにしか依存しないコードになっていて、私もこう書くと思います。 長いシーケンスがくる可能性があるなら if len(x) < len(y): □x, y = y, x を前に入れると思います。
guest

0

様々な回答をありがとうございました。まずはご回答頂いた皆様にお礼を申し上げます。
後述のとおりベストアンサーについては非常に迷ったのですが、最初に"正しい"回答を記載頂いた方にしました。

ここでいう"正しい"とは、私が提示した質問に過不足無く回答頂いているという事を意味します。
つまり、

Pythonで、2つのrangeの間の重複部分を計算する最も良い方法はどのようなものでしょうか?

という質問において、rangeをpythonのbuilt-inのrangeとして理解し、built-inのrangeに"通常想定される"引数を与えた場合に意図する結果が得られるもの、という事でした。(もちろん、最高かどうかは検討の余地があると思いますが。)

ここでいう「通常想定される」という表現もまた曖昧なものですが、rangeにたかだか3つのintないし__index__を持つ引数を渡した時に、メモリがパンクするほどの極端に大きな数でなければ正常に動作するという事を意図していました。
参考: https://docs.python.org/3/library/stdtypes.html#range

したがって、負のstepなども想定した回答が最も望ましいものでしたが、しかし正のstepやstep=1に限定したものであっても、一般的な問題の解としては十分に通用する場合も多く、広くアイデアを検討するにあたっては敢えてアイデアを限定すべきものではないと考え、stepに関する条件などは意図的に記載していませんでした。

頂いた回答内容についてですが、LouiS0616さんのはじめに記載頂いた回答は、日本語でも簡単に記載されているとおり、xとyの関係によって正しい答えが得られないものになっていました。その後に頂いた回答は、後述する元ネタにも(類似パターンの記載はあったとはいえ)なかったもので、かつstepが負の場合なども正しく動作するものでしたが、現時点でこれをベストアンサーとしてしまうのは難しいと思い、melianさんの回答をベストアンサーにさせて頂きました。
日本語でアイデアのみを記載した回答というのも、私が普段検索しているサイトではそんなに出てこないので、回答の方法として参考になりました。
全体的には、私自身もsetを利用する方法を想定していましたが、とはいえsetにするとメモリを不必要に使ってしまう部分もあるので、その辺のコメントがあったりすると嬉しいなと思っていました。(上から目線のようなコメントの仕方になってしまって申し訳ありません)

最後に、なぜこの質問を記載したか?という理由について、言及しておきます。これは、ともすればご回答頂いた皆様に対して不誠実な態度であると思われても致し方ないものと思いますので、予めお詫びさせていただきます。

さて、この質問をした理由のひとつは、日本語でこの情報を記載したサイトをすぐに見つけることができなかった、ということです。
私は普段検索ワードのデフォルトを英語にしていて、
python range intersection
で検索すると、can110さんにご提示いただいたリンクのstack overflowが表示され、一般的な回答例を目にすることができました。
普段であればそれで終わりなのですが、今回はたまたま気になって日本語でも検索をしてみました。
すると、私の検索の仕方が下手なのか、あまりうまく見つけることができませんでした。そこで、この情報を日本語で残しておけば、日本語話者にとっては意味があるのではないか、と思ったのが発端でした。

ただ単に日本語で情報を残すだけであれば、翻訳した上でリンクを貼るなどで十分かもしれませんが、日本語で質問サイトで質問をした場合にはどのような結果になるのか?ということに興味がわきました。
特に、stack overflowではこの質問は+50となっていて、良い質問であると思われます。
実際に、私も検索をしてたどり着いて、これこそがその検索で求めていた内容だと思ったので、+50という評価に特に違和感はありませんでした。
しかし、私の個人的な所感としては、teratailでこのような質問をした場合には、おそらく+50といった評価にはならないのではないか、という事を感じました。むしろ、同程度の質問であっても「追記・修正依頼」がついて、本質的でないやり取りに時間を取られるのではないか?と思ったのでした。

その直感を確認するため、「実際に同様の質問をするとどうなるのか」という実験をするために、この質問が生まれました。

ご回答頂いた皆様からすると、たしかに日本語話者のための情報を集めることには貢献頂いたものの、一方でこのような"実験"に付き合わされたという事で不快感を感じられるかもしれません。それについては改めてお詫び申し上げます。
ただ、この実験を通して、stack overflowとteratailのサイトとしての質の違いみたいなものが少し明らかになったのではないか、という事を感じますので、これをきっかけに「回答のありかた」について少し考えていただくきっかけになれば幸いです。

ここまでお読みいただき、ありがとうございました。

投稿2021/11/24 03:04

yowayowakun

総合スコア7

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

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

LouiS0616

2021/11/24 08:30

素直に面白い試みだと思います。 でもなんかちょっと悔しい気もするので、さらに別解を増やしてみました。ざっと見た感じ、StackOverflowにも無い類の解なのではないでしょうか。
quickquip

2021/11/24 12:08 編集

stackoverflowの質問で、性質が異なる回答が付いて票が別れているのが、同じように再現されたということですね。 コメント、Specify the characteristics of the range (step always equal +1? or can it be -2?) もちゃんと再現されましたね。 My ranges are all in +1 steps. という情報が出ていたらcan110さんの回答の評価が高くなったかもしれませんが、それは再現されませんでしたね。
quickquip

2021/11/24 08:57

1時間ぐらいで「このあたりのどれかだろうな」という回答は揃っていて、あとは「質問者さんが欲しいものはどれだろう。この質問だと判断できないな」状態だったかと。
can110

2021/11/24 12:10 編集

対象の範囲(range)の要素数が2よりも大きいケースも考慮すべきか?はとりあえずいいとしても、それぞれの要素でstepが±1以外で異なるときの「重複」というものをどう考えていたのか?は気になります。 たとえば[1,3,5]と[2,4,6]の重複部分は?ということが気になりました。 すなわち私の回答であげたsoでのavnrさんの回答についてはどう考えてるの?と。
yowayowakun

2021/11/24 15:25 編集

(元ネタはさておき)rangeは https://docs.python.org/ja/3/library/stdtypes.html#ranges によると概念的にはシーケンスを表していて、かつ単調であるため、xとyにおける重複というのはxとyに共通で出現する数の事を意味するのが一般的ではないかと思いますし、それ以外の意味は無いのではないかと思いますが、いかがでしょうか。 その意味で、例えばrange(1,7,2)とrange(2,8,2)の重複部分は無いと思います。 (他の言語では、必ずしも整数と限らない対象についての区間の意味でrangeを使うことももちろんあると思いますが)
can110

2021/11/24 15:50

了解とともに同意です。 「普段であればそれで終わりなのですが」とだけ記載ありましたが 私があげたsoの回答ではstepが±1以外で異なるときの解が満たされていない点、ちゃんと気づいてるのかな?と気になってのコメントでした。 (質問への追記・修正、ベストアンサー選択の依頼欄でのステップ数に関する質問へも回答なかったですし)
quickquip

2021/11/25 02:06

ある程度回答が揃った時点で「stepは+1だけを考えればよいです」という情報が追記されていたら、(soがそうであったように)can110さんの回答が高評価を集めたのか、じわじわと気になってきます。 soは(19:19)質問→(19:23)BAの回答, コメントstepはどうなってるの?→(19:29)+1しか考えない→(19:33)投票数トップの回答 なんですよね。
guest

0

それぞれのリストをset型に変換して、積を取るのが簡単ですね。

投稿2021/11/23 07:34

TakaiY

総合スコア13790

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

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

0

ベストアンサー

python

1>>> intersection = sorted(set(x).intersection(y)) 2>>> print(intersection) 3[7, 8, 9, 10] 4 5>>> rg = range(intersection[0], intersection[-1]+1) 6>>> print(rg) 7range(7, 11)

投稿2021/11/23 07:33

melian

総合スコア20655

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

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

melian

2021/11/24 03:10 編集

ベストアンサーを付けていただいた事には感謝しますが、何か変な汗が出てきますね。。。 内容的には LouiS0616 さんや Karakuri_Polta さんの回答がベストアンサーにふさわしいのではないでしょうか > yowayowakun さん
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問