53152


プログラム初心者です。  
現在、以下のような5文字のアルファベットが大量に並んでいるcsvファイルがあって、このcsvファイルから4文字一致する(一文字だけ異なる)ものだけを全て抜き出してアウトプットしたいと考えております。（abaseとabash、abaseとabateが4文字一致するので、こちらをアウトプットしたいです。）

abase  
abash  
abate  
abbey ・・・・

csvファイルをインポートするところまではできたのですが、4文字一致する(1文字だけ異なる)ところがなかなか分からずにいます。
charAt()で二つのデータを比較する(abaseとabash以下全てのデータを一つずつ比較、最後まで行ったら次はabashとabate以下全てのデータを一つずつ比較)という方法論を考えているのでこちらの方向性でよろしいでしょうか？

## 追記

一致するというのは、文字と、その位置が一致することを指しています。例文では、abaseをabashを指していて、両方ともアウトプットできたらと考えております。


CC BY-SA 4.0
2019-03-02T23:33:34.993
53147
2019-03-03T03:23:25.060
2019-03-03T03:22:41.007
19110
26303
question
java java8
JavaでCSVファイルの読み込みと類似する文字のアウトプットをしたい。


**_charAt()で二つのデータを比較する(abaseとabash以下全てのデータを一つずつ比較、最後まで行ったら次はabashとabate以下全てのデータを一つずつ比較)という方法論を考えているのでこちらの方向性でよろしいでしょうか？_**

何を持って「よろしい」とするのかによります。単に所望の回答が出せれば「よろしい」のなら、それで回答は出せるので「よろしい」と言うことになります。

* * *

ただ、そのような方法だと時間計算量がO(N*N)のオーダーになる(NはCSV中の単語数…CSV中の「5文字のアルファベット」を便宜上「単語」と呼ぶことにします)ので、単語数が増えた時の計算量が大きくならない方が良いいと言うのであれば、アルゴリズムを工夫すべきでしょう。

例えば **abaseとabash、abaseとabateが4文字一致する**
等場合、abaseとabashは`abas*`というパターンで一致する、abaseとabateは`aba*e`というパターンで一致する、と考えられます。

少し見方を変えると、`abas*`というパターンにマッチする単語はabaseとabash、`aba*e`というパターンにマッチする単語はabaseとabate、と言えます。

以下のコードはすべてのパターンとそのパターンにマッチする単語をリストアップし、一つのパターンにマッチする単語が2個以上あれば、それを出力する、という方針で書かれています。

[code]

    package wordsmatch;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     *
     * @author dev
     */
    public class WordsMatch {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            String[] words = {
                "abase",
                "abash",
                "abate",
                "abbey"
            };
            //パターンごとにマッチする単語のListを作る
            Map<String, List<String>> patternToWordsMap = new HashMap<>();
            for( String word: words ) {
                for( String pattern: createPatterns(word) ) {
                    if( !patternToWordsMap.containsKey(pattern) ) {
                        patternToWordsMap.put(pattern, new ArrayList<>());
                    }
                    patternToWordsMap.get(pattern).add(word);
                }
            }
            //マッチする単語Listが2つ以上の単語を含む場合、その単語Listを出力する
            patternToWordsMap.entrySet().stream()
                    .filter(entry -> entry.getValue().size() >= 2)
                    .forEach(entry -> {
                        System.out.println("("+entry.getKey()+")"+entry.getValue());
                    });
        }
    
        /**
         * 4文字一致するパターンを全て生成する
         * "abase"なら、["*base", "a*ase", "ab*se", "aba*e", "abas*"]を返す
         * @param word
         * @return 
         */
        private static String[] createPatterns(String word) {
            String[] patterns = new String[word.length()];
            for( int i = 0; i < word.length(); ++i ) {
                StringBuilder pattern = new StringBuilder(word);
                pattern.replace(i, i+1, "*");
                patterns[i] = pattern.toString();
            }
            return patterns;
        }
    }
    
[/code]

「csvファイルをインポートするところまでは」ご自身でできたという方なら、そこにつながるようにするのはそれほど難しくないだろうと思います。お試しください。できれば「abaseとabash以下全てのデータを一つずつ比較、最後まで行ったら次はabashとabate以下全てのデータを一つずつ比較」の方針で作られたコードと、単語数を増やした時にどの程度の処理速度差が出るのかも比べてみられると良いでしょう。

* * *

結果の出力の方法などが細かく指定されている場合には、このコードの考え方ではうまく対応できないかもしれません。その場合には、ご質問を修正してどんな条件があるのかを明確にしてください。


CC BY-SA 4.0
2019-03-03T03:03:11.213
53152
2019-03-03T03:23:25.060
2019-03-03T03:23:25.060
19110
13972
53147
answer