在Clojure中对数据的大矢量进行排序的最快方法

时间:2017-12-17 22:25:07

标签: sorting clojure

我需要能够以这样的方式存储集合中的数据,即任何给定键集的平均值不大于特定数字。

例如,假设任何给定的3组的“:num”的平均值不能大于或等于10,我有以下设置:

(def my-set
        ({:num 0}
         {:num 5}
         {:num 10}
         {:num 0}
         {:num 5}
         {:num 10}
         {:num 0}
         {:num 5}
         {:num 10}
    ))

在这个集合中,最后3个哈希值不能保持彼此相邻,因为它们的平均值是10,但是可以像这样重新组织集合,因为任何给定3的平均值都是5:

({:num 0} {:num 0} {:num 0} {:num 5})

我的问题是,假设这个集合比这9个条目的样本大得多,可能是数百万,并且整个ENTIRE集合的平均值是5或更少,那么对这些集合进行排序的最快和最有效的方法是什么?那么任何3(或10或100,或任何给定的样本大小)的平均值永远不会达到10?

这是我认为太慢的伪问解决方案:

1)按值分类收集:数字 2)将收集除以2,并将该指数分开 3)交错第一次收集与第二次收集的逆序。

所以第一个集合看起来像:

({:num 10} {:num 10} {:num 10} {:num 5} {:num 5))

第二次收集(逆转):

var mySchema = new Schema({
  'family-name': {
    type: String, 
    default: ''
  }
});

使用interleave,产生的集合将是:

({:num 0} {:num 10} {:num 0} {:num 10} {:num 0} {:num 10} {:num 5} {:num 5} {:num 5})

必须有更好的方法来做到这一点。

2 个答案:

答案 0 :(得分:0)

这是一种方法:

(def data-9
  [{:num 0}
   {:num 0}
   {:num 0}
   {:num 5}
   {:num 5}
   {:num 5}
   {:num 10}
   {:num 10}
   {:num 10}] )

(def data-11
  (into (vec data-9)
    [{:num 0}
     {:num 10}] ))

(defn interleave-by
  [data group-size]
  (let [data-num       (count data)
        part-size      (quot data-num group-size)
        leftover-num   (- data-num (* part-size group-size))
        data-sorted    (sort-by :num data)
        data-leftover  (take leftover-num data-sorted)
        data-use       (drop leftover-num data-sorted)
        data-parts     (partition-all part-size data-use)
        data-reordered (apply mapcat vector data-parts)
        data-final     (reduce into (vec data-leftover) data-reordered)
        ]
    data-final ))

(newline)
(println (interleave-by data-9 3))

data-num => 
9
part-size => 
3
leftover-num => 
0
data-sorted => 
({:num 0}
 {:num 0}
 {:num 0}
 {:num 5}
 {:num 5}
 {:num 5}
 {:num 10}
 {:num 10}
 {:num 10})
data-leftover => 
()
data-use => 
({:num 0}
 {:num 0}
 {:num 0}
 {:num 5}
 {:num 5}
 {:num 5}
 {:num 10}
 {:num 10}
 {:num 10})
data-parts => 
(({:num 0} {:num 0} {:num 0})
 ({:num 5} {:num 5} {:num 5})
 ({:num 10} {:num 10} {:num 10}))
data-reordered => 
({:num 0}
 {:num 5}
 {:num 10}
 {:num 0}
 {:num 5}
 {:num 10}
 {:num 0}
 {:num 5}
 {:num 10})
data-final => 
[[:num 0]
 [:num 5]
 [:num 10]
 [:num 0]
 [:num 5]
 [:num 10]
 [:num 0]
 [:num 5]
 [:num 10]]
(interleave-by data-9 3) => 
[[:num 0]
 [:num 5]
 [:num 10]
 [:num 0]
 [:num 5]
 [:num 10]
 [:num 0]
 [:num 5]
 [:num 10]]

如果没有group-size的整数倍,则更难。这会导致涉及data-leftover

的额外复杂性
(newline)
(println (interleave-by data-11 3))


data-num => 
11
part-size => 
3
leftover-num => 
2
data-sorted => 
({:num 0}
 {:num 0}
 {:num 0}
 {:num 0}
 {:num 5}
 {:num 5}
 {:num 5}
 {:num 10}
 {:num 10}
 {:num 10}
 {:num 10})
data-leftover => 
({:num 0} {:num 0})
data-use => 
({:num 0}
 {:num 0}
 {:num 5}
 {:num 5}
 {:num 5}
 {:num 10}
 {:num 10}
 {:num 10}
 {:num 10})
data-parts => 
(({:num 0} {:num 0} {:num 5})
 ({:num 5} {:num 5} {:num 10})
 ({:num 10} {:num 10} {:num 10}))
data-reordered => 
({:num 0}
 {:num 5}
 {:num 10}
 {:num 0}
 {:num 5}
 {:num 10}
 {:num 5}
 {:num 10}
 {:num 10})
data-final => 
[{:num 0}
 {:num 0}
 [:num 0]
 [:num 5]
 [:num 10]
 [:num 0]
 [:num 5]
 [:num 10]
 [:num 5]
 [:num 10]
 [:num 10]]
(interleave-by data-11 3) => 
[{:num 0}
 {:num 0}
 [:num 0]
 [:num 5]
 [:num 10]
 [:num 0]
 [:num 5]
 [:num 10]
 [:num 5]
 [:num 10]
 [:num 10]]

答案 1 :(得分:0)

  • 这是关于算法的,只是顺带一提 Clojure的。
  • 所要求的并不是这样排序。我们正在寻找一个 数据的排列使得没有相邻的三个(或多个) 数字平均为五或更多。我们可以在我们之前映射到数字 推导出排列。
  • 不需要解决方案。例如,如果任何数字超过 十五,没有一个。
  • 这与subset sum problem类似。可能就是这样 一个确切的解决方案是难以处理的,但贪婪或其他方法会 务实。

我建议您在Computer Science site上尝试解决问题。