• ベストアンサー

配列の中に重複文字列があるか否かをチェックしたいのですが、アルゴリズムを教えてください。

配列10000個の中に次のように文字列が入っているとします。 (実際に使うのはもっとずっと長い文字列が配列内に格納されています。) Data_Array[1] = "GRZRMZCOMKMSG" Data_Array[2] = "DCUIROTLUMWBC" Data_Array[3] = "RGLBMILRPBSMY" . . . Data_Array[9998] = "RSKFDHAHMOESI" Data_Array[9999] = "AQVOXBVNILGOP" Data_Array[10000] = "YNYRUPEXYOGFN" 配列Data_Array[10000]の中に重複文字列がないか探索したいと考えています。 ~普段の手順~ 配列中身を一度テキストに吐き出し、そのテキストをExcelに貼り付ける。 そして、Excelのフィルタ機能で重複文字列を排除。 その後、重複文字列を排除した文字列を保存したものをテキストファイルに保存する。 それをプログラムで読み込んで配列内に格納してから次の処理を続ける といった、効率の悪い方法をとっています。 そこで、プログラム内で処理する方法を次のように考えてみました。 ~思いつく方法~ dim DataArrayTemp[10000] for i = 1 to 10000 flag = 0 // 重複文字がないかチェック for j = i+1 to 10000 ifb Data_Array[i] = Data_Array[j] then // 重複があった場合はflag = 1にする flag = 1 break // 内ループ脱出 endif next // flag = 0であれば重複がない項目 (flag = 1のときは、重複がある) ifb flag = 0 then DataArrayTemp[temp_i] = Data_Array[i] temp_i = temp_i + 1 endif next これは、力技なので配列内の量が多くなると計算時間がかかってしまいます。 ですので、重複しない文字列だけを抽出する効率の良い方法がありましたらどなたか知恵を貸してください。

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

  • ベストアンサー
  • aton
  • ベストアンサー率47% (160/334)
回答No.5

ハッシュ(連想配列)を使ってはどうでしょうか? ~Perlの例~ #$dataArrayTemp[0 .. 9999]には既に値が格納されていると仮定 %temp = (); %nodup = (); for ($i = 0; $i <1000; $i++) { if (defined($temp{$dataArrayTemp[$i]})) { if (defined($nodup{$dataArrayTemp[$i]})) { push(@dups, delete($nodup{$dataArrayTemp[$i]})); } next; } $temp{$dataArrayTemp[$i]} = $i; $nodup{$dataArrayTemp[$i]} = $i; } ソートすると,例えば(一般に最速と言われている)クイックソートならO(N logN)の計算量になりますが,ハッシュを使えば(少なくとも見かけ上の)計算量はO(N)で済みます。 ただ123456zennsinnさんの使っている言語(BASIC系?)にハッシュがあるかどうかは? VB.NETだとHashtableクラスとかありそうですが。 http://www.atmarkit.co.jp/fdotnet/dotnettips/125hashtable/hashtable.html

123456zennsinn
質問者

お礼

ありがとうございました。

その他の回答 (4)

回答No.4

↓ここ打ち間違ってました。正しくは Dim data2 As String() = CType(list.ToArray(GetType(String)), String())

回答No.3

以下のようにコーディングすればスッキリ書けます。 data が元データで data2 が処理後データとなります。 効率は ArrayList や Vector の実装によるので、速いかどうかはよくわかりませんが…。 オブジェクトの再拡張を防止するために、件数がわかっているならNew ArrayList(15000) とか初期容量を十分に取っておく方が望ましいです。 ☆ VBなら  Dim data As String() = {"ABC", "123", "ABC", "ABCD"}  Dim list As New ArrayList  For i = 0 To data.Length - 1   If Not list.Contains(data(i)) Then    list.Add(data(i))   End If  Next  Dim data2 As String() = CType(list.ToArray(GetType,String)), String()) ☆ Javaなら  String[] data = {"ABC", "123", "ABC", "ABCD"};  Vector<String> vc = new Vector<String>();  for(int i = 0; i < data.length; i ++) {   if(!vc.contains(data[i])) {    vc.add(data[i]);   }  }  String[] data2 = vc.toArray(new String[0]);

回答No.2

ヒントというか、私ならソートしてから比較します。 そうすると配列の前後を比較するだけで、内側のループがいらなくなりますね。 重複が1個なのか2個以上あるのかとか、配列の並びに意味があるなら、順番をどこかに保存しておかなければいけないとか細かいことは多々あると思いますがデータ量が多いなら幾分早いんじゃないでしょうか。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

多分, 本質的にソートするのが最速だと思います. ソートすれば, 「重複した文字列」は必ず隣合いますからね. 可能なら直接 Data_Array を使ってソートすればいいですし, ダメでも「Data_Array への添字」の配列をソートするように書けばいい.

関連するQ&A

  • 文字列と文字列をつなげるには

    下記のようにプログラムを作りました。 簡略しているのでわかりづらいと思いますが、 文字の配列と文字の配列を文字の配列に格納したいので、 下記のように$arrayに”.=”として文字列を加えて いますが、うまくいきません。 どのようにしたらいいのでしょうか? ご教授お願いいたします。 while($text[$i] != ""){ if($i==1){ $array[$j] = $feild[$j]; $array[$j] .= " "; $array[$j] .= substr($text[$i], $no, $pos); } }

    • ベストアンサー
    • PHP
  • 多次元配列から重複を削除

    Perlにて$f[i][j]のような2次元配列でデータを格納しています。 ここの[i]列には重複したデータが入っているので、 それを排除して[i]列の重複なしの配列を新たに作りたいのですが うまくいきません。 for ($j=0; $j<= $index; $j++){ if($chlist[j]==$f[$i][0]){ $chlist[j]==$f[$i][0]; last; } } こんな感じで作ってみたのですが永遠にデータが入りません。

  • 文字列の配列

    文字列の配列 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 のようにIPアドレスが一行に一つづつ書き込まれたテキストがあります。 ここから、それぞれのIPアドレスを文字列として配列に書き込みたいのですが、どうしたらよいのでしょうか。 IPアドレスの数だけ配列を始めに宣言して、それぞれに書き込んでいくのでは手間がかかりすぎてしまいます。 単純に数値の羅列なら scanfを使い、配列に格納できるのですが、文字列になるとどうしたらいいのかわかりません。 よろしくお願いいたします。

  • 文字列になっている配列を‥

    以下の値がDBに文字列の項目に登録されています。 DB から値を取得したのはいいのですが文字列なので foreach でグルグルしようとすると怒られてしまいます。 配列の型に変換できればいいのですが(array)だとうまく行かないしどうすればいいかどなたかご教授願えないでしょうか。 よろしくお願いします。 ■値(文字列でDBに格納されてます‥) array( 1=>'a', 2=>'b', 3=>'c', 10=>array( 'A'=>1, 'B'=>'hoge1', ), 11=>array( 'A'=>2, 'B'=>'hoge2', ), 12=>array( 'A'=>3, 'B'=>'hoge3', ), )

    • 締切済み
    • PHP
  • 配列にある文字列を1つの変数に改行付きで格納する方法

    配列にある文字列を1つの変数に改行付きで格納する方法 Array ( [0] => レタス [1] => トマト [2] => きゅうり ) などの配列を $yasai 変数へ ------ レタス トマト きゅうり ------ と格納してテキスト表示させたいのですが、どのようにすれば可能でしょうか? そもそも可能なのでしょうか?ご存知の方、いらっしゃいましたら宜しくお願いします。

    • ベストアンサー
    • PHP
  • ruby 配列の中の文字列を全部数値にしたい

    array=%w(1 2 3 4) のような文字列の配列があるとします。 これを数値の配列にしたいです。 以下の様にしてみました。 array=array.inject([]){|a,v| a<< v.to_i } これでも出来ましたが、もっとrubyらしい方法ってあったら教えて下さい。

    • ベストアンサー
    • Ruby
  • 文字列の取得について

    配列には下記のような文字列が表示されています。 $array[$i]="text kldfjk kldof" このような長い文字列の場合にそこの ”text"とという文字列が表示されている場合には フラグを立てるというプログラムにしたいのですが、 このような処理ではうまくいきません。 何かよい解決策があれば教えていただけたらうれしいです。よろしくお願いいたします。 $single_1=strpos($array[$i],"text"); $flag=1;

    • ベストアンサー
    • PHP
  • 文字列を配列に…。

    VBはまだ始めたばかりで本当に初歩的なことかもしれませんが分かる方がおられたら是非教えて下さい。 text1.textから取り込んだ文字列を”一文字ずつ”(Dim a(100) as stringで宣言した)配列に格納したいのですがどうしたらいいのでしょうか?? <例>text1.textに"abc"と入力しcommandbuttonを押すとa(0)に"a"がa(1)に"b"がa(2)に"c"が格納されるといったかんじです。 ちなみに今私がしたいのはtext1.textに、ある文字列を入れその文字列を文字コードに変換しそれを一文字分ずつ+1してまたそのコードを文字に直しtext2.textに出力するというものです(ようは簡単な暗号化ですね)。 私はAscとChrコマンドを利用して1文字ずつコードをずらしていこうと思っているのですが、他に良い方法などあるのでしょうか?? 本当に初心者でどのようにしらたよいのか分かりません…。 どなたか分かりやすく教えていただけませんでしょうか?? お願いします。

  • 文字列を配列に入れる方法

    初歩的な質問で申し訳ありません。 文字列型のデータを1文字ずつ順番に配列に格納する方法を教えてください。 よろしくお願いしますっ。

  • C言語 文字列格納

    テキストファイルから整数データ又は文字列を読み込んで配列に格納する動作についての質問です。 テキストファイルが1行区切りの整数型なら1次元配列で for(i = 0; i < maxSize; i++) { fscanf(fp,"%d", &data[i]); } テキストファイルが1行区切りの文字列なら2次元配列で for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%s", &data[i][300]) == EOF) break; } for(j = 0; j < i; j++) printf("%s\n", data[j]); みたいな具合に格納できたんですが、 テキストファイルが1行区切りのデータではなく、空白文字区切りの文字データだった場合、それぞれどのようにして配列に格納すればいいかがわかりません。 イメージとしては、1文字目から見ていって空白が出ればそこで切って格納していくというかんじなのですが・・・ 質問の内容がわかりにくいかもしれませんが、是非教えてください。お願いします。

専門家に質問してみよう