根据值压缩列表

时间:2015-06-19 09:23:14

标签: java

有一个简单的类,如:

public class Label {
    public String id;
    public double amount;
}

拥有包含以下值的列表(列表按amount升序排序):

id        amount
----------------
1742      10
1742      11
1647      12
4217      13
1647      14
1742      15

是否有一种简单的方法来压缩列表,以便只保留id的最低金额。因此,压缩后,列表应如下所示:

id        amount
----------------
1742      10
1647      12
4217      13

6 个答案:

答案 0 :(得分:1)

如果我理解正确,您想要从Label对象列表中删除双打。 有一些简单的方法,例如为列表创建自定义比较器:

文档:https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html Stack Overflow post:Collections sort(List<T>,Comparator<? super T>) method example

另一种方法是使用地图,因为据我所知,你可以使用两个值,因此使用类似TreeMap和自定义比较器^也可能是一个解决方案。 否则,您可以开发自己的排序算法,同时将对象与另一个对象进行比较,同时根据您的标准排序和跳过双打,例如Buble排序可以调整以做到这一点,大多数排序技术也是如此。

答案 1 :(得分:0)

许多方法都可以做到这一点。怎么样(完全未经测试,很可能不会编译):

public static List<Label> deduped(List<Label> yourSortedList) {
    List<Label> output = new LinkedList<>();
    assert yourSortedList.size() > 0;
    Label lastVal = yourSortedList.get(0);
    for (Label l : yourSortedList) {
        if (!lastVal.id.equals(l.id)) {
            output.add(lastVal);
            lastVal = l;
         }
    }
    output.add(lastVal);
    return output;
}

如果上面没有至少一个错误,我会非常惊讶,但希望你能得到一般的想法。

答案 2 :(得分:0)

这是一种做法。方法makeUnique()将仅保留那些具有最小金额的标签。

<style>
body{
   font-size : 20px;
}
</style>

答案 3 :(得分:0)

几乎每个人都是正确的,但谈到简单的方式

只需使用java.util.Set

即可

并覆盖Label类的equals()hashCode()方法。

除此之外还有很多方法。

执行此操作的方法之一

List<Label> originalList = new ArrayList<Label>();
            // above conatins your original List

            List<Label> result = new ArrayList<Label>();
            Set<String> label = new HashSet<String>();

            for( Label item : originalList ) {
                if( label.add( item.getId() ) {
                    result.add( item );
                }
            }

您需要在班级中使用getId()的Getter方法

答案 4 :(得分:0)

由于列表已经在金额上排序,您只需要在列表第一次出现时将对象标签包括在内。如果使用字典存储已输入元素的 id ,则可以生成包含确切元素的新列表。像这样:

    public static List<Label> compact(List<Label> l)
    {
        Set<String> ids = new HashSet<>();
        List<Label> toret = new ArrayList<>();

        for(Label label: l) {
            if ( !ids.contains( label.id ) ) {
                ids.add( label.id );
                toret.add( label );
            }
        }

        return toret;
    }

由于我们使用列表,因此Antoher的可能性是使用相同的列表进行压缩&#34;就位#34;考虑到这种可能性使用较少的内存,但速度较慢(因为它必须在循环中每次查找元素&#39; i,这在LinkedList中可能很昂贵)。

public static void compactInPlace(List<Label> l)
{
    Set<String> ids = new HashSet<>();

    for(int i = 0; i < l.size(); ++i) {
        if ( !ids.contains( l.get( i ).id ) ) {
            ids.add( l.get( i ).id );
        } else {
            l.remove( i );
            --i;
        }
    }

    return;
}

在此处找到代码:http://ideone.com/B4Gggt

希望这有帮助。

答案 5 :(得分:0)

使用Java 8 Streams,你可以这样做:

import java.util.Optional;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public static List<Label> getDistinctMinLabels(List<Label> labels) {
    return labels
        .stream()
        .collect(
            // group by label id
            // and of each group get the label with the minimum amount
            Collectors.groupingBy(
                label -> label.id, 
                Collectors.minBy((l1, l2) -> Double.compare(l1.amount, l2.amount)) 
            )
        )
        .entrySet()
        .stream()
        .map(Entry::getValue)
        .map(optional -> optional.get()) // Collectors.minBy returns an Optional<Label>
        .collect(Collectors.toList());   
}

此功能效率最高,但在标签未排序时也有效。