• ベストアンサー

ランキングで似た配列を探す。似ている確率も求めたい

「要素数が固定の配列」「あるいは先頭から要素を5つぐらいを切り取った配列」で、 「自分と似た配列」を「似ている確率順」で表示させたいのですが、どうすればいいでしょうか? ■似ている ・内容が一致 ・順番も一致? ・一致している数? ・先頭からの要素数が一致している方が優先? 特にこうしたい、という強い希望があるわけではないのですが、「似ている配列」を求めたいとき、どういう方法が考えられるのか知りたく、質問しました

  • re97
  • お礼率80% (601/744)
  • PHP
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
noname#244856
noname#244856
回答No.3

【実装例】 http://ideone.com/b1T4dS <?php $arrs = array( 'arr1' => array(1, 2, 3, 4, 5), 'arr2' => array(101, 102, 103, 104, 105), 'arr3' => array(3, 4, 2, 5, 1), 'arr4' => array(5, 3, 4, 2, 1), ); foreach ($arrs as $base_name => $base_arr) { $copies = $arrs; unset($copies[$base_name]); echo "【{$base_name}の他に対する類似度】\n"; $base_str = implode("\0", $base_arr); $results = array(); foreach ($copies as $target_name => $target_arr) { $target_str = implode("\0", $target_arr); similar_text($base_str, $target_str, $percent); $results[$target_name] = $percent; } arsort($results); foreach ($results as $target_name => $percent) { printf("%s -> %01.2f%%\n", $target_name, $percent); } echo "\n"; }

re97
質問者

お礼

「再度の回答」&「具体的な実装例」を提示いただき、ありがとうございました。 ・大変参考になりましたー

その他の回答 (2)

noname#244856
noname#244856
回答No.2

implode関数とsimilar_text関数を組み合わせれば比較的ラクに書けそうな気がします。 implode() http://php.net/manual/ja/function.implode.php これを使って比較する配列の要素を一度全て結合し、文字列としてください。 結合文字はカンマだと中身の文字列と被る可能性があるので、NULL文字辺りを入れとけばいいんじゃないでしょうか。 similar_text() http://php.net/manual/ja/function.similar-text.php 類似性を3番目の参照渡しにした引数で受け取ってください。 このアルゴリズムは渡す順序によって計算結果に差が出るみたいです。 そんなに気にする必要もなさそうですが。

re97
質問者

お礼

回答ありがとうございます。 >similar_text() ・この関数、初めて知りましたー

回答No.1

「似ている」の定義にもよりますが・・・ グラフにした時の形が似ている、つまり、例えば {1,2,3,4,5}と{101,102,103,104,105}が「完璧に似ている」というのであれば、引き算した結果の配列{100,100,100,100,100}の分散を求めて、0に近い順に出力すれば良いでしょう。 数字を色に置き換えて2つ並べた時に似ているように見えるのを似ているというのであれば、 例えばレーベンシュタイン距離(編集距離)が短い順に出力する、等の方法が考えられます。 http://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%BC%E3%83%99%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%A4%E3%83%B3%E8%B7%9D%E9%9B%A2 配列の要素が一致しているが、同順である必要がないというのであれば、一旦その中身をソートしてからレーベンシュタイン距離を測る、等の工夫が考えられます。

re97
質問者

お礼

回答ありがとうございました。 >グラフにした時の形が似ている ・似ている、を考えるとき、こういうアプローチの仕方もあるのかと、驚きました ・リンク先も含め、色々参考になりましたー

関連するQ&A

  • 配列一致(要素順番は違うが内容は同じ)を確認したい

    ■前提 ・連想配列ではない、普通の配列が2つある ・2つの配列要素数は同一(例えばそれぞれ五つ) ■質問 ・仮に2つの配列要素内容が同じである(但し順番は違う)時、2つの配列要素内容が同じであることを確認するには、どうすればよいでしょうか?

    • ベストアンサー
    • PHP
  • C言語の配列のコピーについて質問です。

    intを要素とする二つの配列a、bとその配列の要素数を受け取り、配列aのすべての要素の値を配列bにコピーする関数を定義し、その関数の機能を確認するプログラム作成するという問題について質問です。 (1)配列aを配列bに「先頭から順番に」コピーする関数を作成する (2)配列aを配列bに「後ろから順番に」コピーする関数を作成する ただし、配列の要素数(例では4)が変更されても処理できる関数を作成したいです。また、配列の要素の値は関数main()内で表示したいです。 [ヒント] (1)関数宣言の例 void array_copy(コピー元の配列, コピー先の配列, 配列の要素数) [実行結果の例] (1)先頭から順番にコピーする コピー前 a[0]: 1 b[0]: 0 a[1]: 2 b[1]: 0 a[2]: 3 b[2]: 0 a[3]: 4 b[3]: 0 コピー後 a[0]: 1 b[0]: 1 a[1]: 2 b[1]: 2 a[2]: 3 b[2]: 3 a[3]: 4 b[3]: 4 (2)後ろから順番にコピーする コピー前 a[0]: 1 b[0]: 0 a[1]: 2 b[1]: 0 a[2]: 3 b[2]: 0 a[3]: 4 b[3]: 0 コピー後 a[0]: 1 b[0]: 4 a[1]: 2 b[1]: 3 a[2]: 3 b[2]: 2 a[3]: 4 b[3]: 1 #include <stdio.h> void array_copy() から始めて int main(void) { とプログラムを作成したいのですが教えてください。

  • C#での動的配列作成方法について

    はじめまして、 現在ASP.NET、C#で開発をしております。 そこで、質問です。 C#で二次元配列を作成し、データを格納します。 二次元配列は宣言時はサイズがわかってません。 ループで回った回数分、最初(第一要素数)の要素数が決定します。 二つ目の要素数の数は最初からきまっています(固定用素数)。 string[][] string[,] arraylist などがあると思いますが、上記の場合どういう風に配列を作成していったらいいのでしょうか? 動的にサイズを変更できる配列の作り方、データ格納方法、データ表示方法を教えてください。 よろしくお願いします。

  • [C言語] 配列が添字の意味を失う理由

    はじめまして。こんばんは。 早速ですが、下記のソースコードは、 配列aの各要素の内容を先頭から順に調べ、最初に0であった要素の添字番号を表示する。 という内容の、C言語のプログラムです。(C++でコンパイルするためmain()はint型に指定) そこで、このプログラムを実行していて腑に落ちない点として、 プログラムの挙動を見る限り、 タイトルに書いたとおり、 「配列が添字の意味を失っている」という事なんです。 普通に配列の添字と考えれば、 while文の条件式は、 int i=0; while(a[i]) { i++; } なので、a[0]になるはずなので、 普通に考えれば 条件式の中身としては  配列a[0] が 配列a[0] になるまでi++をするとなるはずです。 しかしながら、このプログラムは、 初期値に「0」が入っている要素まで探し続けます。 なぜ、 「配列が添字の意味を失うのか?」 どなたか、この疑問にお答えしていただけますと幸いです。 「プログラムの内容」 配列aの各要素の内容を先頭から順に調べ、最初に0であった要素の添字番号を表示する。 「表示結果」 a[2]= 0 「ソースコード」 #include<stdio.h> int main() { int a[]={3,0,7,8,5,5,8}; int i=0; while(a[i]) { i++; } printf("a[%2d]=%2d \n",i,a[i]); }

  • 配列の定義について

    配列とは、同じ形式のデーターを連続した記憶領域で確保するためのものである。 配列を構成する個々の領域を要素と呼び、要素の位置を添え字で示す。 Javaでは配列の先頭の要素を(0)番目と呼ぶ。 今、hairetsuという名前で10個の整数からなる配列を定義したい。 この場合の配列は(0)番目から始まり、終端は(9)番目である。 これを定義するには (int[] hairetsu;) (hairetsu = new int[10];) のように2行で行う方法と、 (int[] hairetsu = (new int[10];) のように、一行で行う方法がある。 Javaでは定義済みの配列の要素数は、配列変数名.(length)で知ることができ、 終端は(length + 1)番目となる。 したがって(length + 1)番目以降を使おうとすると、 配列要素の範囲外で(例外)が発生する。 この文章の( )の中は間違っていますか?

    • ベストアンサー
    • Java
  • 配列のことでなのですが

    配列で先頭から順番に文字列を格納していきたいのですがどのような方法があるでしょうか? ただforループなどで順番に繰り返すのではなくて、文字列を入力する度に配列の最後尾に文字列を格納していきたいのですが、 例えば for(i=0;i<=10;i++){ scanf("%s",hairetu[i]) } のような方法ではなく配列の中に文字列を前から順番に格納したいです。 詳しい方は知識をかしていただけるとありがたいです。

  • 確率教えて下さい!

    1から36までの数がそれぞれ書かれた36枚のカードをランダムに5枚並べる(例:19.1.4.36.7) そのあともう一度その36枚のカードをランダムに5枚並べる この2回並べたカードの数字が順番も含め完全一致する確率 を教えてください

  • 乱数での確率

    乱数に確率をつけることはできるでしょうか? たとえば配列にA、B、Cの3つの要素を収めておいて、  Aが出る確率=50%  Bが出る確率=30%  Cが出る確率=10% といったように確率を設定してランダム表示させたいのですが。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • 配列要素

    ファイルから読み込んだ、要素数の分からない配列があります。 前から2つずつ順に表示したいのですが、どうしたらよいでしょうか? <ファイルfruit.datの内容>―――→商品名(全角) 半角数字 りんご 210 いちご 350 みかん 390 ぶどう 500 レモン 100 柿 200 <<表示>> 商品:りんご 210円    いちご 350円    みかん 390円 商品:ぶどう 500円 商品:レモン 100円    柿 200円 open(RF,"<fruit.dat"); while(<RF>){ @data=split; ---<ここで処理>--- } close(RF); このような感じです。 配列@dataから2つずつ表示させたいんです。 良い方法がありましたら、教えてください。

    • ベストアンサー
    • Perl
  • 配列について。

    Redim した後   For i LBound(配列) To UBound(配列)    作業   Next i をしているのですが、配列の要素数を別プロセスで 計算させる場合、必ずしも要素が存在するとはかぎ りません。 その場合エラーがでるわけですが、このように配列 の中身が存在しない場合はどのように回避できるの でしょうか? VB6&Windows2000です。

専門家に質問してみよう