我正在尝试对一组数据进行排序,使其看起来像是概率分布函数的直方图(我假设目前正态分布)。
我有一个条目列表:
private static final class SortableDatasetEntry{
Number value;
Comparable key;
public SortableDatasetEntry(Number value, Comparable key){
this.value = value;
this.key = key;
}
}
一个例子:
我有这些项目:{1,2,3,4,5,6,7,8,9}
编辑:
我想要的排序列表:{1,3,5,7,9,8,6,4,2}
(或类似的东西)数字并不总是那么整洁(即简单地按奇数/偶数排序也不会)。我有一个部分解决方案,涉及按常规顺序(从最低到最高)排序,然后通过每次插入到中间将该列表复制到另一个,因此插入的最后一个项目(到中间)是最大的。我还是想找一个用比较器做这个的方法。
这非常棘手,因为它没有按 value
的绝对值排序,而是按照集合中的均值(value
)的距离进行排序,然后以某种方式移动了这些值最接近平均值的是居中。我知道compareTo函数必须是“可逆的”(我忘了正确的术语)。
奖励积分:如何确定数据的正确分布(即,如果假设不正常)。
答案 0 :(得分:1)
首先计算均值并将其存储在名为mean
的变量中。接下来,当您将条目插入SortableDatasetEntry时,请使用value - mean
作为每个条目的实际值,而不是value
。
答案 1 :(得分:0)
对于我所看到的,你可能想得到一个“平均距离”元组,值并用第一个条目“平均距离”对元组列表进行排序。
答案 2 :(得分:0)
您会发现将直方图构建为 @property(nonatomic, readonly) NSTimeInterval playableDuration
更容易。
Map
请注意Histogram
的意图要构建直方图,第一步是“对”值范围进行“bin” - 即将整个值范围划分为一系列小间隔 - 然后计算每个间隔中落入的值。
答案 3 :(得分:0)
会是这样的:
public List<Integer> customSort(List<Integer> list) {
Collections.sort(list);
List<Integer> newList = new ArrayList<Integer>();
for (int i = 0; i < list.size(); i += 2) {
newList.add(list.get(i));
}
if (list.size() % 2 == 0) {
for (int i = 1; i < list.size(); i += 2) {
newList.add(list.get(list.size() - i));
}
} else {
for (int i = 1; i < list.size(); i += 2) {
newList.add(list.get(list.size() - i - 1));
}
}
return newList;
}
工作?我输入{1,2,3,4,5,6,7,8,9}
并获得{1,3,5,7,9,8,6,4,2}
,{1,2,3,4,5,6,7,8}
提供{1,3,5,7,8,6,4,2}
。
答案 4 :(得分:0)
仅使用自定义Comparator
,您无法在单一种类中完成此操作。
但是,就地仍然是可行的,没有额外的参考集合。
您当前的方法不是就地,但可能是最容易实现和理解的方法。除非内存中的集合大小是一个问题,否则请考虑使用当前的方法。
单一排序的自定义比较器
您所需的订单取决于升序。鉴于未分类的数据,您的Comparator
在第一次排序时没有升序。
就地方法
您可以就地创建所需的订单。
以下假设基于0的指数。
一种方法可以使用两种方法。首先,按升序排序。用索引标记每个对象。在第二种比较器中,具有偶数索引的所有对象将小于具有奇数索引的所有对象。具有偶数索引的对象将按升序排序。具有奇数索引的对象将按降序排序。
另一种方法是自定义排序算法,支持从虚拟索引到物理索引的映射。排序算法将在虚拟索引空间中创建升序。您的索引映射将按照您希望的顺序在物理内存中进行布局。这是一个未经测试的索引映射草图:
private int mapVirtualToPhysical( int virtualIndex, int countElements ) {
boolean isEvenIndex = ( 0 == (index % 2));
int physicalIndex = isEvenIndex ? (index / 2) : (countElements - (index/2) - 1);
return physicalIndex;
}
这些中的任何一个都优先是初始排序,然后是O(n)系列的掉期。但是,我还没有确定掉期顺序。到目前为止,我提出的最佳方法是按顺序获得左尾,但右尾要么需要后续排序,要么堆栈。
答案 5 :(得分:0)
对于大型数据集,您可以在SortableEntry
构造函数确定时使用该方法,使用随机数生成器确定此特定条目将占用的图表的哪一侧(最左侧或右侧):
static final class SortableEntry<T>{
Number value;
Comparable<T> key;
int hr;
static Random rnd = new Random();
public SortableEntry(Number value, Comparable<T> key){
this.value = value;
this.key = key;
this.hr = rnd.nextInt(2) == 0 ? -1 : 1; // here
}
}
额外hr
变量的要点是使任何&#34;对&#34;进入大于任何&#34;左&#34;反之亦然。如果两个比较条目中的hr
相同,请按实际key
进行比较,同时考虑hr
的符号:
static final class SortableEntryComparator<T> implements Comparator<SortableEntry<T>> {
@Override
public int compare(SortableEntry<T> e1, SortableEntry<T> e2) {
if (e1.hr == e2.hr)
return e1.hr < 0 ? e1.key.compareTo((T) e2.key) : e2.key.compareTo((T) e1.key);
else
return e1.hr - e2.hr;
}
}
现在进行一项小测试:
@Test
public void testSort() {
List<Integer> keys = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
12, 25, 31, 33, 34, 36, 39, 41, 26, 49,
52, 52, 58, 61, 63, 69, 74, 83, 92, 98);
List<SortableEntry<Integer>> entries = new ArrayList<>();
for (Integer k : keys) {
entries.add(new SortableEntry<Integer>(0, k));
}
entries.sort(new SortableEntryComparator<Integer>());
System.out.println(entries);
}
// output:
// [12, 26, 33, 36, 39, 40, 49, 50, 52, 60, 61, 63, 80, 90, 98, 100, 92, 83, 74, 70, 69, 58, 52, 41, 34, 31, 30, 25, 20, 10]
// the highest key (100) is not precisely in the center,
// but it will tend to occur in the center when dataset is large.