- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我认为这很容易找到预制的,但似乎我在网上找到的任何解决方案都只能解决部分问题。
我想对用户提供的文件名列表进行排序(这些文件大多以人和/或地址命名),有时使用不同的语言(主要是德语,带有一些法语和意大利语在这里和那里混合,很少有任何其他西方语言)。
这个想法是以(德国)用户通常认为理智的方式呈现这个列表。这意味着顺序应遵循 locale.GERMAN 的 java.text.Collator,但同时期望对字符串中的数字进行异常(exception)处理,因此“10”出现在“2”之后".
我找到了在网络上进行自然排序的代码,但它依赖于逐字符比较(而 Collator 不支持)。我可以用子字符串破解一些东西,但在比较器内部,我认为在每个比较调用上创建多个子字符串并不是最明智的想法。
有什么想法可以有效地实现这一点(在执行时间和实现 时间),或者更好的是一个经过测试和随时可用的实现?
最佳答案
这是已接受答案中的改编代码(基于 The Alphanum Algorithm )。代码经过优化以减少垃圾产生并处理前导零 (01 < 001 < 2)。它还被通用化,现在更加灵活,因为它不再局限于 java.lang.String,而是现在采用 java.lang.CharSequence。玩得开心:
import java.text.Collator;
import java.util.Comparator;
/**
* Comparator for ordering by Collator while treating digits numerically.
* This provides a "natural" order that humans usually perceive as 'logical'.
*
* It should work reasonably well for western languages (provided you
* use the proper collator when constructing). For free control over the
* Collator, use the constructor that takes a Collator as parameter.
* Configure the Collator using Collator.setDecomposition()/setStrength()
* to suit your requirements.
*/
public class AlphanumComparator implements Comparator<CharSequence> {
/**
* The collator used for comparison of the alpha part
*/
private final Collator collator;
/**
* Create comparator using platform default collator.
* (equivalent to using Collator.getInstance())
*/
public AlphanumComparator() {
this(Collator.getInstance());
}
/**
* Create comparator using specified collator
*/
public AlphanumComparator(final Collator collator) {
if (collator == null)
throw new IllegalArgumentException("collator must not be null");
this.collator = collator;
}
/**
* Ideally this would be generalized to Character.isDigit(), but I have
* no knowledge about arabic language and other digits, so I treat
* them as characters...
*/
private static boolean isDigit(final int character) {
// code between ASCII '0' and '9'?
return character >= 48 && character <= 57;
}
/**
* Get subsequence of only characters or only digits, but not mixed
*/
private static CharSequence getChunk(final CharSequence charSeq, final int start) {
int index = start;
final int length = charSeq.length();
final boolean mode = isDigit(charSeq.charAt(index++));
while (index < length) {
if (isDigit(charSeq.charAt(index)) != mode)
break;
++index;
}
return charSeq.subSequence(start, index);
}
/**
* Implements Comparator<CharSequence>.compare
*/
public int compare(final CharSequence charSeq1, final CharSequence charSeq2) {
final int length1 = charSeq1.length();
final int length2 = charSeq2.length();
int index1 = 0;
int index2 = 0;
int result = 0;
while (result == 0 && index1 < length1 && index2 < length2) {
final CharSequence chunk1 = getChunk(charSeq1, index1);
index1 += chunk1.length();
final CharSequence chunk2 = getChunk(charSeq2, index2);
index2 += chunk2.length();
if (isDigit(chunk1.charAt(0)) && isDigit(chunk2.charAt(0))) {
final int clen1 = chunk1.length();
final int clen2 = chunk2.length();
// count and skip leading zeros
int zeros1 = 0;
while (zeros1 < clen1 && chunk1.charAt(zeros1) == '0')
++zeros1;
// count and skip leading zeros
int zeros2 = 0;
while (zeros2 < clen2 && chunk2.charAt(zeros2) == '0')
++zeros2;
// the longer run of non-zero digits is greater
result = (clen1 - zeros1) - (clen2 - zeros2);
// if the length is the same, the first differing digit decides
// which one is deemed greater.
int subi1 = zeros1;
int subi2 = zeros2;
while (result == 0 && subi1 < clen1 && subi2 < clen2) {
result = chunk1.charAt(subi1++) - chunk2.charAt(subi2++);
}
// if still no difference, the longer zeros-prefix is greater
if (result == 0)
result = subi1 - subi2;
} else {
// in case we are working with Strings, toString() doesn't create
// any objects (String.toString() returns the same string itself).
result = collator.compare(chunk1.toString(), chunk2.toString());
}
}
// if there was no difference at all, let the longer one be the greater one
if (result == 0)
result = length1 - length2;
// limit result to (-1, 0, or 1)
return Integer.signum(result);
}
}
编辑 2014-12-01:Konstantin Petrukhnov 在评论中指出的固定版本。
关于java - 结合字母顺序和自然顺序(又名。用户理智排序),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12640280/
我想要抓取“链接”、“标题”和“摘要” 我怎样才能抓取这个? 我试过了 import requests import json url = 'http://www.arxiv-sanity.com/t
假设我只想通过传递指向该函数的函数指针来公开我的一个文件中的函数。将该函数声明为 static 是否安全?是否允许编译器执行任何会使我的函数指针无效的柔道,或者使其在该文件的上下文之外变得毫无意义,因
这个问题在这里已经有了答案: Turn a string into a valid filename? (26 个回答) 关闭 3 个月前。 我想从一些随机的 Unicode 字符串(可能包含任何内容
我从其他人的帐户收到了一个 github 存储库备份。该项目正在运行 gatsby、sanity cms 并通过 netlify 托管。当我提取存档并在本地保存文件夹时,只需执行“yarn insta
我是一名优秀的程序员,十分优秀!