如何从具有重复条目的筛选列表中删除特定索引?

时间:2023-01-28 00:16:48

I have a TableView backed by a SortedList wrapping a FilteredList wrapping an ObservableList. The items in the filtered list can be duplicated. That is to say, it can be the case that list.get(5) == list.get(10).

我有一个由SortedList支持的TableView,它包装了一个包含ObservableList的FilteredList。过滤列表中的项目可以重复。也就是说,可能是list.get(5)== list.get(10)的情况。

The user can select rows on the TableView and press delete. When they do, the items that are selected are supposed to be removed, and no others.

用户可以在TableView上选择行并按删除。当他们这样做时,应该删除所选择的项目,而不删除其他项目。

I have tried two solutions, both of which present problems:

我尝试了两种解决方案,两者都存在问题:

Using list.remove ( Object ) on the underlying ObservableList - Because the list can have duplicated items, all copies of the object are removed rather than just the selected one(s).

在底层ObservableList上使用list.remove(Object) - 因为列表可以包含重复项,所以删除了对象的所有副本,而不仅仅是选定的副本。

public void removeItemsAtIndices ( List <Integer> indices ) {

    List <Item> removeMe = new ArrayList<Item> ();

    for ( int index : indices ) {
        removeMe.add( currentListSorted.get( index ) );
    }

    items.removeAll( removeMe );
}

using list.remove ( index ) on the SortedList - The filtered list throws an UnsupportedOperationException.

在SortedList上使用list.remove(index) - 筛选的列表抛出UnsupportedOperationException。

public void removeItemsAtIndices ( List <Integer> indices ) {
    Collections.sort( indices, Collections.reverseOrder() );

    for( int index : indices ) {
        currentListSorted.remove( index ); //Exception here
    }
}

Here is how I'm setting up my Lists:

以下是我设置列表的方法:

private final ObservableList <Item> items = FXCollections.observableArrayList(); 
private final FilteredList <Item> currentListFiltered = new FilteredList <Item>( items, p -> true );
private final SortedList <Item> currentListSorted = new SortedList <CurrentListTrack>( currentListFiltered );

Is there some way to remove items:

有没有办法删除项目:

  1. From a sorted list
  2. 从排序列表

  3. Targeting by index of the filtered & sorted list
  4. 按过滤和排序列表的索引进行定位

  5. Without removing non-targeted duplicates?
  6. 没有删除非目标重复项?

The only solution I can come up with at the moment is to make it so each item is unique (i.e it's impossible that list.get(5) == list.get(10)). I am hoping to avoid this by finding another solution.

我现在能想出的唯一解决方案是使每个项目都是唯一的(即list.get(5)== list.get(10)是不可能的)。我希望通过寻找另一种解决方案来避免这种情况。


P.S. If for some reason it is useful, here is the code that determines the selected indices:

附:如果由于某种原因它很有用,这里是确定所选索引的代码:

removeMenuItem.setOnAction( new EventHandler <ActionEvent>() {
    @Override
    public void handle ( ActionEvent event ) {
        ObservableList <Integer> selectedIndexes = currentListTable.getSelectionModel().getSelectedIndices();
        List <Integer> removeMe = new ArrayList<> ( selectedIndexes );
        removeItemsAtIndices ( removeMe );
    }
});

1 个解决方案

#1


2  

TransformationList (of which both SortedList and FilteredList are implementations) has a getSourceIndex(int index) method that "translates" the index in the transformed list to the index in its source (underlying) list. So currentListSorted(index) gives the index in the filtered list of an item that has the provided index in the sorted list, and currentListFiltered(index) gives the index in the original items list of an item that has the provided index in the filtered list.

TransformationList(其中SortedList和FilteredList都是实现)具有getSourceIndex(int index)方法,该方法将转换列表中的索引“转换”为其源(底层)列表中的索引。因此,currentListSorted(index)给出在已排序列表中具有提供的索引的项目的已过滤列表中的索引,并且currentListFiltered(index)给出在已过滤列表中具有提供的索引的项目的原始项目列表中的索引。

So you can do

所以你可以做到

items.remove(currentListFiltered.getSourceIndex(
    currentListSorted.getSourceIndex(index)
));

to remove the item at a specific index in the "index coordinates" of the visible table items (the sorted list).

删除可见表项(排序列表)的“索引坐标”中特定索引处的项目。

Of course, you need to be careful with the loops in your code here, because the indexing will change when items are removed. (This would be true too if you were simply removing items by index from a simple list.)

当然,这里需要小心代码中的循环,因为删除项目时索引会发生变化。 (如果你只是简单地从一个简单的列表中删除项目,那也是如此。)

So you probably need something along the following lines:

所以你可能需要以下几点:

List<Integer> indicesToBeRemoved = new ArrayList<>();
for (int index : indices) { // indices in the sorted list
    indicesToBeRemoved.add(currentListFiltered.getSourceIndex(
        currentListSorted.getSourceIndex(index)));
}
// sort with largest index first, as removing an item with
// a given index will not change the indices of items with small indices:
indicesToBeRemoved.sort(Comparator.reverseOrder()); 
for (Integer index : indicesToBeRemoved) {
    // be careful to explicitly unbox the Integer here, 
    // to avoid collision between remove(Object) and remove(int):
    items.remove(index.intValue());
}

#1


2  

TransformationList (of which both SortedList and FilteredList are implementations) has a getSourceIndex(int index) method that "translates" the index in the transformed list to the index in its source (underlying) list. So currentListSorted(index) gives the index in the filtered list of an item that has the provided index in the sorted list, and currentListFiltered(index) gives the index in the original items list of an item that has the provided index in the filtered list.

TransformationList(其中SortedList和FilteredList都是实现)具有getSourceIndex(int index)方法,该方法将转换列表中的索引“转换”为其源(底层)列表中的索引。因此,currentListSorted(index)给出在已排序列表中具有提供的索引的项目的已过滤列表中的索引,并且currentListFiltered(index)给出在已过滤列表中具有提供的索引的项目的原始项目列表中的索引。

So you can do

所以你可以做到

items.remove(currentListFiltered.getSourceIndex(
    currentListSorted.getSourceIndex(index)
));

to remove the item at a specific index in the "index coordinates" of the visible table items (the sorted list).

删除可见表项(排序列表)的“索引坐标”中特定索引处的项目。

Of course, you need to be careful with the loops in your code here, because the indexing will change when items are removed. (This would be true too if you were simply removing items by index from a simple list.)

当然,这里需要小心代码中的循环,因为删除项目时索引会发生变化。 (如果你只是简单地从一个简单的列表中删除项目,那也是如此。)

So you probably need something along the following lines:

所以你可能需要以下几点:

List<Integer> indicesToBeRemoved = new ArrayList<>();
for (int index : indices) { // indices in the sorted list
    indicesToBeRemoved.add(currentListFiltered.getSourceIndex(
        currentListSorted.getSourceIndex(index)));
}
// sort with largest index first, as removing an item with
// a given index will not change the indices of items with small indices:
indicesToBeRemoved.sort(Comparator.reverseOrder()); 
for (Integer index : indicesToBeRemoved) {
    // be careful to explicitly unbox the Integer here, 
    // to avoid collision between remove(Object) and remove(int):
    items.remove(index.intValue());
}