在Clojure中对数据的大矢量进行排序的最快方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Clojure中对数据的大矢量进行排序的最快方法相关的知识,希望对你有一定的参考价值。
我需要能够以这样一种方式存储集合中的数据,即任何给定密钥集的平均值不大于特定数字。
例如,假设任何给定的3个集合的“:num”的平均值不能大于或等于10,并且我有以下集合:
(def my-set
({:num 0}
{:num 0}
{:num 0}
{:num 5}
{:num 5}
{:num 5}
{:num 10}
{:num 10}
{:num 10}
))
在这个集合中,最后3个哈希值不能保持彼此相邻,因为它们的平均值为10,但是可以像这样重新组织集合,因为任何给定的3的平均值将是5:
(def my-set
({:num 0}
{:num 5}
{:num 10}
{:num 0}
{:num 5}
{:num 10}
{:num 0}
{:num 5}
{:num 10}
))
我的问题是,假设这个集合远远大于9个条目的样本,可能是数百万个,并且整个集合的平均值是5或更少,那么对这些集合进行排序的最快和最有效的方法是什么任何3(或10或100,或任何给定样本大小)的平均值从未达到10?
这是我的伪代码解决方案,我觉得它太慢了:
1)按值排序集合:数字2)将集合除以2并分割为该索引的数量3)交错第一集合与第二集合的逆序。
所以第一个集合看起来像:
({:num 0} {:num 0} {:num 0} {:num 5})
第二次收集(逆转):
({:num 10} {:num 10} {:num 10} {:num 5} {:num 5))
使用interleave,产生的集合将是:
({0} {当然,无论是{10},是否{0},是否{10},是否{0},{10}当然,无论是5} {5} {当然,无论是5})
必须有一个更好的方法来做到这一点。
答案
这是一种方法:
(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]]
另一答案
- 这是关于算法的,并且只是偶然地与Clojure有关。
- 所需要的不是这样排序。我们正在寻找数据的排列,使得没有相邻的三个(或多个)数字平均为五个或更多。在导出排列之前,我们可以映射到数字。
- 不需要解决方案。例如,如果任何数字超过十五,则没有一个。
- 这看起来类似于subset sum problem。很可能一个确切的解决方案是难以处理的,但贪婪或其他方法将是切实可行的。
我建议你试试Computer Science site上的问题。
以上是关于在Clojure中对数据的大矢量进行排序的最快方法的主要内容,如果未能解决你的问题,请参考以下文章