Maksimal qiymatni kamaytirish yordamida topish

Java fon bilan jilovlash uchun yangi. Menda quyidagi jadval bor va jadvalni eng yuqori saviyaga ega bo'lgan shahardagi mahsulotlar bilan taqqoslaydigan xash xaritasiga aylantirish kerak. Misol uchun, chiqdi quyidagicha bo'lishi kerak:

{"Pencil": "Toronto"
"Bread": "Ottawa"}

(def table [
    {:product "Pencil"
    :city "Toronto"
    :year "2010"
    :sales "2653.00"}
    {:product "Pencil"
    :city "Oshawa"
    :year "2010"
    :sales "525.00"}
    {:product "Bread"
    :city "Toronto"
    :year "2010"
    :sales "136,264.00"}
    {:product "Bread"
    :city "Oshawa"
    :year "nil"
    :sales "242,634.00"}
    {:product "Bread"
    :city "Ottawa"
    :year "2011"
    :sales "426,164.00"}])

Men hozirga qadar shunday deb o'ylayman:

(reduce (fn [product-cities {:keys [product sales]}]
         (update-in product-cities [product] (fnil conj []) sales))
       {}
       table)

Bu natijani ishlab chiqaradi:

{"Bread"
["136,264.00"
"242,634.00"
"426,164.00"],
 "Pencil" ["2653.00" "525.00"]}

Qanday qilib men har bir shaharning savdolarini taqqoslashim mumkin va faqatgina eng yuqori savdoda shahar nomini saqlab qolasiz? Bu bilan juda qiyin vaqt bor. Rahmat

2

6 javoblar

clojure.core-da ushbu kod uchun juda qulay bo'lgan max-key funktsiyasi mavjud.

(defn process [table]
  (let [parseDouble #(Double/parseDouble (clojure.string/replace % #"," ""))]
    (->> table
         (group-by :product)
         (map (comp (juxt :product :city)
                    (partial apply max-key (comp parseDouble :sales))
                    val))
         (into {}))))

user> (process table)
;;=> {"Pencil" "Toronto", "Bread" "Ottawa"}

kaliti maksimal ayrıştırılmış savdo qiymati bo'lgan bir guruhda (qisman qo'llaniladigan max-key (komple parseDouble: sales)) qismidir.

8
qo'shib qo'ydi
Men deyarli bir xil javobni yozgan bo'lar edim - o'zgarish, men hozirda kodini ga transduser bilan ishlatishni yoqtirishimga to'g'ri keladi, bu kamida bitta dangasalik yukini bekor qiladi. Bu kabi: ({{} (map (comp ,)) (guruh tomonidan: mahsulot jadvali)) .
qo'shib qo'ydi muallif glts, manba

Savdo qiymatlarini satrlardan raqamlarga aylantiradigan ba'zi funktsiyalar kerak. Sotuv raqamlari haqiqatan ham raqamlar ekanligiga ishonch hosil qilish uchun bu hiylani amalga oshirish kerak:

(->> table
     (group-by :product)
     (map (fn [[k v]]
            [k (first (sort-by (comp - identity :sales) v))]))
     (into {})
     vals
     (map (comp #(apply vector %)
                vals
                #(select-keys % [:product :city])))
     (into {}))

Replace identity with your string->number function.

Shubhasiz, bu vazifani yaxshilash mumkin ...

3
qo'shib qo'ydi

Mana buni qanday qilishim kerak. Men qidiruv kodini ko'rish uchun spyx-pretty </html> Tupelo kutubxonasidan foydalanganman osonroq ( API hujjatlarini bu erda topishingiz mumkin ). Kod:

(ns tst.demo.core
  (:use demo.core
        tupelo.test)
  (:require [tupelo.core :as t]
            [clojure.string :as str] ))
(t/refer-tupelo)

(def table
  [{:product "Pencil" :city "Toronto" :year "2010" :sales "2653.00"}
   {:product "Pencil" :city "Oshawa" :year "2010" :sales "525.00"}
   {:product "Bread" :city "Toronto" :year "2010" :sales "136,264.00"}
   {:product "Bread" :city "Oshawa" :year "nil" :sales "242,634.00"}
   {:product "Bread" :city "Ottawa" :year "2011" :sales "426,164.00"}])

(defn str->double
  "Convert a string like '2,123.97' to a double like 2123.97 "
  [str-val]
  (let [no-commas (str/replace str-val #"," "")
        dbl-val   (Double/parseDouble no-commas)]
    dbl-val))

(dotest
  (let [table-num (forv [item table]
                    (update item :sales str->double))
        grouped   (group-by :product table-num)
        >>        (spyx-pretty grouped)
        group-max (forv [group grouped]
                    (do
                      (spyx-pretty group)
                      (let [records        (xsecond group)
                            >>             (spyx-pretty records)
                            records-sorted (sort-by :sales > records)
                            >>             (spyx-pretty records-sorted)
                            max-rec        (xfirst records-sorted)
                            ]
                        (spyx max-rec))))]
    (spyx-pretty group-max)))

Natijalar quyidagilardir:

---------------------------------------
   Clojure 1.9.0-beta1    Java 9.0.1
---------------------------------------

Testing tst.demo.core

grouped => 
{"Pencil"
 [{:product "Pencil", :city "Toronto", :year "2010", :sales 2653.0}
  {:product "Pencil", :city "Oshawa", :year "2010", :sales 525.0}],
 "Bread"
 [{:product "Bread", :city "Toronto", :year "2010", :sales 136264.0}
  {:product "Bread", :city "Oshawa", :year "nil", :sales 242634.0}
  {:product "Bread", :city "Ottawa", :year "2011", :sales 426164.0}]}

group => 
["Pencil"
 [{:product "Pencil", :city "Toronto", :year "2010", :sales 2653.0}
  {:product "Pencil", :city "Oshawa", :year "2010", :sales 525.0}]]

records => 
[{:product "Pencil", :city "Toronto", :year "2010", :sales 2653.0}
 {:product "Pencil", :city "Oshawa", :year "2010", :sales 525.0}]

records-sorted => 
({:product "Pencil", :city "Toronto", :year "2010", :sales 2653.0}
 {:product "Pencil", :city "Oshawa", :year "2010", :sales 525.0})
max-rec => {:product "Pencil", :city "Toronto", :year "2010", :sales 2653.0}

group => 
["Bread"
 [{:product "Bread", :city "Toronto", :year "2010", :sales 136264.0}
  {:product "Bread", :city "Oshawa", :year "nil", :sales 242634.0}
  {:product "Bread", :city "Ottawa", :year "2011", :sales 426164.0}]]

records => 
[{:product "Bread", :city "Toronto", :year "2010", :sales 136264.0}
 {:product "Bread", :city "Oshawa", :year "nil", :sales 242634.0}
 {:product "Bread", :city "Ottawa", :year "2011", :sales 426164.0}]

records-sorted => 
({:product "Bread", :city "Ottawa", :year "2011", :sales 426164.0}
 {:product "Bread", :city "Oshawa", :year "nil", :sales 242634.0}
 {:product "Bread", :city "Toronto", :year "2010", :sales 136264.0})
max-rec => {:product "Bread", :city "Ottawa", :year "2011", :sales 426164.0}

group-max => 
[{:product "Pencil", :city "Toronto", :year "2010", :sales 2653.0}
 {:product "Bread", :city "Ottawa", :year "2011", :sales 426164.0}]

Birinchi qadam, barcha mag'lubiyatga qiymatlarini suzuvchi nuqtaga aylantirishdir. So'ngra, agar biz har bir qadamni fikrlash qulayligi uchun ajratib turishni yoqtirsam va shuning uchun qo'yadigan bo'lsa, unda men o'zimning kodni guruhga qo'shish uchun funktsiyasidan foydalanamiz. har bir qadamda disk raskadrovka chiqishi.

IMHO bu REPLni ishlatishdan ko'ra ancha sodda, chunki men eng sevimli IDE/muharriri ichida qolaman va men yozgan narsalar faylga saqlanadi, shuning uchun men darhol yo'qolishim kerak.

1
qo'shib qo'ydi
Agar siz yadro bo'lmagan kutubxonalardan foydalanmoqchi bo'lsangiz, uni kodda aniqroq qilishingiz kerak. forv - bu tupelo funksiyasi to'g'ri? Nima uchun T/forv emas? Men o'ylashim mumkin bo'lgan yagona istisno - bu core.async , bu juda kulgili funktsiya nomlari bilan ajralib turadi.
qo'shib qo'ydi muallif Chris Murphy, manba
Mening dalillarim o'zingiz uchun qulaylik emas, balki boshqalar uchun o'qiydiganlik haqida edi.
qo'shib qo'ydi muallif Chris Murphy, manba
(t/refer-tupelo) satri joriy nom maydoniga bir qator vars degan ma'noni anglatadi (: so'zini ishlatish o'rniga). Men bu usulni har doim ishlataman va qo'shimcha kodni spyx , spyks-pretty , forv , xfirst , xsecond va hokazo. Agar barcha manbani ns va (t/refer-tupelo) ni tanlasangiz, nom maydoni haqida aniqroq ma'lumotga ega bo'lishga roziman.
qo'shib qo'ydi muallif Alan Thompson, manba

Siz quyidagi kabi foydalanishingiz mumkin:

(into {} (map (fn [[k {:keys [city sales]}]] [k city])
                (reduce (fn [product-cities {:keys [product sales city]}]
                          (let [sales (Double/parseDouble (clojure.string/replace sales "," ""))
                                prev-sales (get-in product-cities [product :sales] 0)]
                            (if (> sales prev-sales)
                              (assoc product-cities product {:sales sales :city city})
                              product-cities)))
                        {}
                        table)))

P.S. Oldindan javob berilishi mumkin bo'lsa-da ...

1
qo'shib qo'ydi

Bu erda oraliq ma'lumot strukturalarini saqlaydigan juda tez versiya:

(let [parse #(Double/parseDouble (clojure.string/replace % "," ""))]
  (reduce (fn [m {:keys [product sales city] :as cand}]
            (let [sales-d (parse sales)]
              (update m product (fn [prev]
                                  (if (or (nil? prev) (< (:sales prev) sales-d))
                                    (assoc cand :sales sales-d) 
                                    prev)))))
          {} products))
0
qo'shib qo'ydi

@Leetwinski javobiga asoslangan spinoff g'oyasi. Idea - bu tilda biroz ko'proq asosiy bo'lganligi uchun savdo-sotiq qiymatlari bo'yicha saralashdan foydalanish.

(defn process [table]
  (let [parseDouble #(Double/parseDouble (clojure.string/replace % #"," ""))
        parsedTable (for [a table] (update a :sales parseDouble))]
    (->> parsedTable
         (sort-by :sales)
         (group-by :product)
         vals        
         (map (comp (juxt :product :city) last))
         (into {}))))
 (process table)
=>{"Bread" "Ottawa" "Pencil" "Toronto"}
0
qo'shib qo'ydi