12

A={a1,a2,a3,...an}との 2 つのリストが与えられた場合、 all の場合に限りB={b1,b2,b3,...bn}ます。A>=Bai>=bi

2 つのリストの論理比較が組み込まれていますが、 はありA==BませんA>B。このように各要素を比較する必要がありますか

And@@Table[A[[i]]>=B[[i]],{i,n}]

これを行うためのより良いトリックはありますか?

編集: 皆さんに感謝します。

さらに質問があります:

N 個のリストの中から最大リスト (存在する場合) を見つける方法は?

Mathematica を使用して、同じ長さの N 個のリストの中で最大のリストを効率的に簡単に見つける方法はありますか?

4

5 に答える 5

18

方法1:私はこの方法を好みます。

NonNegative[Min[a - b]]

方法2:これはただの楽しみです。Leonidが指摘したように、私が使用したデータには少し不公平な利点があります。ペアワイズ比較を行い、必要に応じてFalseとBreakを返す場合、ループの方が効率的である可能性があります(ただし、通常はmmaでループを回避します)。

result = True;
n = 1; While[n < 1001, If[a[[n]] < b[[n]], result = False; Break[]]; n++]; result

10 ^ 6の数字のリストに関するいくつかのタイミング比較:

a = Table[RandomInteger[100], {10^6}];
b = Table[RandomInteger[100], {10^6}];

(* OP's method *)
And @@ Table[a[[i]] >= b[[i]], {i, 10^6}] // Timing

(* acl's uncompiled method *)
And @@ Thread[a >= b] // Timing

(* Leonid's method *)
lessEqual[a, b] // Timing

(* David's method #1 *)
NonNegative[Min[a - b]] // Timing

タイミング2


編集:誤解を招く可能性があるため、方法2のタイミングを削除しました。そして、方法#1は一般的なアプローチとしてより適しています。

于 2012-01-16T20:07:19.460 に答える
8

例えば、

And @@ Thread[A >= B]

仕事をするべきです。

編集:一方、これは

cmp = Compile[
  {
   {a, _Integer, 1},
   {b, _Integer, 1}
   },
  Module[
   {flag = True},
   Do[
    If[Not[a[[p]] >= b[[p]]], flag = False; Break[]],
    {p, 1, Length@a}];
   flag],
  CompilationTarget \[Rule] "C"
  ]

は 20 倍高速です。ただし、20倍も醜いです。

編集 2: David は C コンパイラを使用できないため、ここにすべてのタイミング結果を示しますが、2 つの違いがあります。まず、彼の 2 番目の方法は、すべての要素を比較するように修正されました。次に、aそれ自体と比較しますが、これは最悪のケースです (それ以外の場合、上記の 2 番目の方法では、条件に違反するために最初の要素まで比較するだけで済みます)。

(*OP's method*)
And @@ Table[a[[i]] >= b[[i]], {i, 10^6}] // Timing

(*acl's uncompiled method*)
And @@ Thread[a >= b] // Timing

(*Leonid's method*)
lessEqual[a, b] // Timing

(*David's method #1*)
NonNegative[Min[a - b]] // Timing

(*David's method #2*)
Timing[result = True;
 n = 1; While[n < Length[a], 
  If[a[[n]] < b[[n]], result = False; Break[]];
  n++]; result]

(*acl's compiled method*)
cmp[a, a] // Timing

ここに画像の説明を入力

したがって、コンパイルされた方法ははるかに高速です (David の 2 番目の方法とここでのコンパイルされた方法は同じアルゴリズムであり、唯一の違いはオーバーヘッドであることに注意してください)。

これらはすべてバッテリー電源で動作しているため、ランダムな変動がある可能性がありますが、代表的なものだと思います。

編集 3: ruebenko がコメントで示唆したように、このように に置き換えPartた場合Compile`GetElement

cmp2 = Compile[{{a, _Integer, 1}, {b, _Integer, 1}}, 
  Module[{flag = True}, 
   Do[If[Not[Compile`GetElement[a, p] >= Compile`GetElement[b, p]], 
     flag = False; Break[]], {p, 1, Length@a}];
   flag], CompilationTarget -> "C"]

thencmp2は の 2 倍の速さcmpです。

于 2012-01-16T20:02:36.157 に答える
4

質問の要素として効率について言及したので、次の関数が役立つ場合があります。

ClearAll[lessEqual, greaterEqual];
lessEqual[lst1_, lst2_] :=
   SparseArray[1 - UnitStep[lst2 - lst1]]["NonzeroPositions"] === {};

greaterEqual[lst1_, lst2_] :=
   SparseArray[1 - UnitStep[lst1 - lst2]]["NonzeroPositions"] === {};

これらの機能はかなり効率的です。@Davidのソリューションは、依然として2〜4倍高速です。極端な速度が必要で、リストが数値(整数または実数で構成されている)の場合は、おそらくCへのコンパイルを使用する必要があります(@aclのソリューション、およびその他の場合も同様です)。演算子)。

同じ手法を使用して(およびを実装するUnitize代わりにを使用して) 、他の比較演算子(、、、、)を実装できます。そのことを覚えておいてください。UnitStepequalunequal><==!=UnitStep[0]==1

于 2012-01-16T20:37:01.283 に答える
3

のような比較関数Greater, GreaterEqual, Equal, Less, LessEqualは、さまざまな方法でリストに適用することができます (それらはすべて、質問のアプローチのバリエーションです)。

2 つのリストを使用:

 a={a1,a2,a3};
 b={b1,b2,b3};

および数値エントリを持つ 2 つのインスタンス

na={2,3,4}; nb={1,3,2}; 

あなたが使用することができます

And@@NonNegative[na-nb]

シンボリック エントリのリストあり

And@@NonNegative[na-nb]

与える

NonNegative[a1 - b1] && NonNegative[a2 - b2] && NonNegative[a3 - b3]

一般的な比較では、次のような一般的な比較関数を作成できます

listCompare[comp_ (_Greater | _GreaterEqual | _Equal | _Less | _LessEqual), 
         list1_List, list2_List] := And @@ MapThread[comp, {list1, list2}]

として使用

listCompare[GreaterEqual,na,nb]

を与えTrueます。シンボリック エントリあり

listCompare[GreaterEqual,a,b]

論理的に等価な式 を与えるa1 <= b1 && a2 <= b2 && a3 <= b3

于 2012-01-16T20:49:27.507 に答える
2

パックされた配列や数値コンパレータなどを扱う場合、>=David の方法 #1 に勝るものはありません。

ただし、単純な算術演算に変換できない、より複雑なテストの場合は、別の方法が必要です。

特にアンパックされたリストの一般的な良い方法は、以下を使用することInnerです:

Inner[test, a, b, And]

これは事前にすべての比較を行うわけではないため、場合によってはより効率的And @@ MapThread[test, {a, b}]です。これは違いを示しています。

test = (Print[#, " >= ", #2]; # >= #2) &;

{a, b} = {{1, 2, 3, 4, 5}, {1, 3, 3, 4, 5}};

Inner[test, a, b, And]
1 >= 1
2 >= 3

False
And @@ MapThread[test, {a, b}]
1 >= 1
2 >= 3
3 >= 3
4 >= 4
5 >= 5

False

配列がパックされていて、特にリターンが得られる可能性Falseが高い場合は、David の方法 #2 などのループが適切なオプションです。次のように書いたほうがよいかもしれません。

Null === Do[If[a[[i]] ~test~ b[[i]], , Return@False], {i, Length@a}]
1 >= 1
2 >= 3

False
于 2012-01-17T07:33:11.347 に答える