我有一个项目列表(即字符串),我需要对其进行排序/过滤。
最终结果应不包含任何重复(简单),我会将它们全部放入Set中。所以我现在有一套字符串。
更多解释..
我还有一个方法x来计算两个字符串之间的差异量(使用levenstein距离)。
问题:
在将新字符串string
插入我的集set
之前,我想使用x
和其他任何方法之间的方法string
检查 levenstein距离 set
中的字符串以及如果x
返回>=3
而不是我不应该添加它。
我最好的做法是什么?除了要插入的每个set
的迭代槽string
之外?
答案 0 :(得分:2)
通过Set
进行迭代将是您最好的选择,因为没有任何内置的Set
实现可以帮助您缩小可能性。
答案 1 :(得分:2)
我玩过如何做到这一点的想法。没有任何迭代次数,我想不出办法做到这一点。
假设您有一个名为distance(String,String):int
的方法,它返回两个字符串之间的给定距离。
String x = "Obi-wan"; //this is the item subject to eval addition
List<String> items = new ArrayList<String>(asList("Luke","Yoda","Anakin"));
if (items.filter(s -> distance(s, x) >= 3).getFirst() == null) {
items.add(x);
}
如果您使用JDK8 Preview,则可以使用上述代码立即执行此操作。 Iterables.getFirst()方法不会迭代整个集合,只会在找到满足条件的第一个元素之前。
否则,您可能必须实现Predicate接口和过滤方法。
interface Predicate<T> {
public boolean eval(T o);
}
public static void main(String[] args) {
final String x = "Obi-wan"; //this is the item subject to eval addition
List<String> items = new ArrayList<String>(asList("Luke","Yoda","Anakin"));
Predicate<String> p = new Predicate<String>() {
public boolean eval(String s){
return distance(s, x) >= 3;
}
};
if(filter(items, p).isEmpty()){
items.add(x);
}
}
public static <T> List<T> filter(List<? extends T> items, Predicate<? super T> predicate){
List<T> destiny = new ArrayList<T>();
for(T item : items){
if(predicate.eval(item){
destiny.add(item);
}
}
return destiny;
}
或者,您可以在找到满足条件的第一项后停止过滤。
答案 2 :(得分:1)
创建集合时可以使用自定义比较器。在比较器中,如果它们相同(根据常规字符串比较规则)或者它们的Levenstein距离符合您的标准,则返回两个字符串相同。
当您的comaprator说两个字符串相同时,新字符串不会插入到集合中。 (注意,这意味着字符串的最终结果可能取决于插入的顺序)
更新:处理有关总排序的评论:
使用上述建议的比较器会使得结果依赖于插入顺序(如上所述),因为使用的Levenstein距离标准没有定义总排序,因此任何其他解决方案都是如此。
OTOH,一旦一个字符串通过了不相等的测试并被插入到集合中,集合中的其他字符串将不会比较此字符串,因此集合中的字符串将使用它们的自然字符串排序,这确实定义了总排序,因此在集合的内部操作(例如排序)中不会出现进一步的不一致。