2

私はこれにかなり頻繁に遭遇します。この形式のいくつかのバージョンのデータのバッチがあります(CSV、XMLで保存されていますが、問題ありません)。

key1|value1
key1|value2
key1|value3
key2|value4
key2|value5
etc.

そして、この形式でそれを処理できる必要があります:

data[key1] => [value1, value2, value3]
data[key2] => [value4, value5]
etc.

AからBに変換するための最良のアプローチは何ですか?私は通常、このようなリスト(擬似コード)をループしますが、配列構築コードを繰り返さなければならないのは好きではありません。

data = []
values = []
currentKey = ""
foreach (line in inputData) {
    key, value = split(line)
    if ((currentKey != "") and (currentKey != key)) {
        data[currentKey] = values
        values = []
    }
    currentKey = key
    values.add(value)
}
// this is the part I don't like, but it's necessary to capture the last group
data[currentKey] = values

少なくともJavascript、C#、Perl、およびPHPでこれを行わなければならなかったので、私は特に言語に名前を付けていません。素晴らしい言語固有のソリューションがあるが、私は本当に最も効率的な一般的なアルゴリズムのアプローチを探しています。

4

2 に答える 2

1

コードを次のように変更できます。

data = {}

currentKey = ""

foreach (line in inputData) {

    key, value = split(line)
    if (currentKey != key) {
        data[key] = [] // like data.put(key,new ArrayList<String>()) in java
    }
    data[key].add(value) // like data.get(key).add(value) in java
    currentKey = key
}
于 2012-08-02T17:17:58.507 に答える
1

これが解決策です。まず、地図を作成します。データファイルのエントリごとに、キーと値を見つけます。キーがマップにあるかどうかを確認します。そうでない場合は、そのキーの新しい値を含む新しいリストをマップに追加します。キーがすでにマップにある場合は、新しい値をリストに追加するだけです。

def hash = [:]
new File("test.data").eachLine { String line ->
    def (key,value)  = line.split(/\|/)
    hash.get(key, []) << value
}

println hash

次のマップが出力されます。

[key1:[value1, value2, value3], key2:[value4, value5]]

を追跡する必要はありませんcurrentKey

編集:これはGroovyで書かれていますが、他の言語でもまったく同じように実装する必要があります。hash.get()キーの値、または指定されたデフォルト値(上記のスニペットでは空のリスト)を返し、左シフト(<<)演算子はリストに何かを追加します。

于 2012-08-02T17:53:53.713 に答える