1

編集:

データは本当にこのように見えます。

1,000-00-000、GRABBUS、OCTOPUS ,, M、26-Nev-12、、05 FRENCH TOAST ROAD ,, VACANT、ZA、1867、(001)111-1011、(002)111-1000 ,,

専有情報が含まれているので、ばかげているように見せなければなりません。

これは、clojure-csvを使用してベクトルのベクトルを作成する前の状態です。

簡単にするために解析後の数値を使用しましたが、値に減らされていません。clojure-csvで解析されたデータから特定の列を選択して、より小さなcsv行を作成したいと思います。

ご迷惑をおかけしましたことをお詫び申し上げます。

編集終了:

いつreduceを使用するか、代わりにpmapを使用するかをどのように決定しますか?

少し前に、reduceについてブログにコメントがありました。具体的には、reduceは一般的に並列化できないが、map(pmap)は並列化できるというコメントがありました。

削減を使用する場合と使用しない場合で違いが生じるのはいつですか。次のような例では、違いがありますか?

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

(def csv-row [1 2 3 4 5 6 7 8 9])
(def col-nums [0 1 4])

(defn reduce-csv-rowX
    "Accepts a csv-row and a list of columns to extract, and
     reduces the csv-row to the selected list using a list comprehension."
    [csv-row col-nums]
        (for [col-num col-nums
            :let [part-row (nth csv-row col-num nil)]]
            part-row))

(defn reduce-csv-row
    "Accepts a csv-row and a list of columns to extract, and
     reduces the csv-row to the selected list."
    [csv-row col-nums]
    (reduce
        (fn [out-csv-row col-num]
            (let [out-val (nth csv-row col-num nil)]
                (if-not (nil? out-val)
                    (conj out-csv-row out-val))))
        []
        col-nums))

編集:

(defn reduce-csv-row "抽出するcsv-rowと列のリストを受け入れ、csv-rowを選択したリストに縮小します。" [csv-row col-nums](reduce(fn [out-csv- row col-num](let [out-val(nth csv-row col-num nil)](conj out-csv-row out-val)))[] col-nums))

4

4 に答える 4

5

一般に、最も単純なコードを記述できる関数を使用する必要があります。これは通常、可能な最も具体的な機能を意味します。この場合、操作は、列番号のリストを列の行の値のリストに変換するものと考えることができます。これは に対応するmapので、おそらく を使いたいでしょうmap。で書くこともできますreduceが、この場合はmapへの呼び出しで再実装してreduceいるため、おそらく間違った方法です。

reduceただし、正しい選択の場合もあります。リストを任意の値に「縮小」しようとしている場合は、mapまったく役に立ちません。この場合、reduceが必要であり、操作が並列化できないため、reduceも並列化できません。

コードが理想的でない理由にさらに興味があるreduce場合は、アプリケーション固有のコードを抽象化すると、次のようになります。

(reduce
 (fn [out-list current-val]
   (let [out-val (f current-val)]
     (if-not (nil? out-val)
       (conj out-list out-val))))
 []
 col-nums)

1 つの複雑な要因はif-not通話です。現時点では、バグがあります-out-valが nil の場合は、これまでに見つけたものをすべて破棄して最初からやり直します (からの戻り(if-not (nil? out-val) (conj out-list out-val))はnil のnil場合であるため、次の として使用されます)。あなたの他の実装には nil チェックがなく、この nil チェックはバグが多いため (おそらく使用されたことがないため)、無視できると想定しています。この時点で、あなたのコードはout-valnilout-list

(reduce
 (fn [out-list current-val]
   (let [out-val (f current-val)]
     (conj out-list out-val)))
 []
 col-nums)

これは、完全に有効な (怠惰ではありませんが) の実装ですmap。代わりに実際の呼び出しを使用すると、実際mapには特定の問題に関連していないこのコードをすべて削除し、代わりに実際にやろうとしていることに集中できます。ivant のソリューションを見ると、これがもたらす効果を確認できます。

于 2012-03-22T17:17:15.603 に答える
3

map を使用したソリューションは次のようになります。

(defn reduce-csv-rowM [csv-row col-nums]
  (pmap (fn [pos] (nth csv-row pos)) col-nums))

それは自明に並列化可能であり、csv-row がベクトルの場合、n 番目は非常に高速であるため、問題ありません。

したがって、あなたの場合、他の2つよりも理解しやすく、高速になる可能性があるため、マップソリューションが最適だと思います。

一般に、map と reduce は互換性がなく、実際に一緒に使用すると非常に便利です (Google の map-reduce テクニックのように)。

于 2012-03-22T15:28:04.100 に答える
1

少し異なる形式で応答を返す選択キーを使用することもできます。

(select-keys [1 2 3 4 5 6 7 8 9] [0 1 4])
;==> {4 5, 1 2, 0 1}

つまり、キーから値へのマップです。マップの方が見栄えが良いですが、他の seq でも機能します。

clojure.set/project を見ることもできます。これは select-keys に似ていますが (実際には内部で使用しています)、1 行だけではなく、テーブル全体を対象としています。

于 2012-03-23T08:05:48.093 に答える
1

resu と map は非常に優れた組み合わせであり、これらは非常に頻繁に一緒に使用されるため、現在 map-reduce は一般的な業界用語になっています。一般に、map はデータを集計可能な形式に変換し、集計データを 1 つの回答に減らすために使用されます。リダクション関数が可換である場合、reduce は並列化できます。たとえば、並列削減は では問題+なく、 ではうまく機能しません/

  • コレクション(リストやベクターなど)mapを生成する場合に使用します。
  • 42 のような単一の値reduceを生成する場合に使用します
于 2012-03-22T22:04:05.053 に答える