Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Remove duplicate entries from QListWidget?



  • Hello,

    I'm writing a program that will involve creating a ListWidget. This list will only include file URLs. The only way user will be able to enter URLs is by clicking the "Browse" button and selecting multiple files. It is possible to import the same file twice, and the URL would appear on the list twice as well. In order to avoid future errors, I want to automatically remove any possible duplicates from the list. I did this with the following code, however, I have a feeling like it's not the most efficient solution:

    def browse_func(self):
        url = QFileDialog.getOpenFileNames(self, "Open a file", "", "All Files(*)::*txt",)
    
        for i in url[0]:
            self.list_widget.addItem(i)
    
        items = []
        for i in range(self.list_widget.count()):
            items.append(self.list_widget.item(i).text())
    
        unique_items_set = set(items)
    
        self.list_widget.clear()
        for i in unique_items_set:
            self.list_widget.addItem(i)
    

    Here's my logic: add items to Qlist -> retrieve all entries into python list -> convert that list into a set (remove duplicates) -> clear QList -> add items from existing set into QList.

    There should be some method that would do it more efficiently, but I couldn't find it.

    Let me know if you need more details in order to understand the problem. I'm still new to python and PyQT5, and it's the first time asking for help in the forum.

    Thank you!



  • @Sebastian1993 said in Remove duplicate entries from QListWidget?:

    (item, Qt::MatchFixedString | Qt::MatchCaseSensitive)

    My bad, that bit is C++ (I used to do Python, now doing C++). You should know that will be the following in Python (you will come across C++ examples all the time):

    (item, Qt.MatchFixedString | Qt.MatchCaseSensitive)
    

    plus something like

    from PySide2.QtCore import Qt
    

    at the head of your file, which you'll need for many things Qt.

    Also (I think!) I corrected addItem(i) to addItem(item). If what you pasted is verbatim, you're missing an extra indent on that line.


  • Lifetime Qt Champion

    @Sebastian1993 Why not checking whether an URL is already in the list and only add it if not?



  • @Sebastian1993
    As @jsulm says. If you want to reduce the number of lines of code to the minimum of 3 lines, at the possible expense of a tiny bit of efficiency (which won't be noticeable unless you have loads of items), you might go:

    for item in url[0]:
        if not self.list_widget.findItems(item, Qt.MatchFixedString | Qt.MatchCaseSensitive):  # edit: corrected
            self.list_widget.addItem(item)
    

    As it stands with your code using getOpenFileNames(), since that only allows picking from one directory there won't be any duplicates anyway.



  • @jsulm The program will work without this feature, but I still want to add it as it's a good experience for me

    @JonB I'm trying to implement your code but doesn't work, getting red highlights there:

    (item, Qt::MatchFixedString | Qt::MatchCaseSensitive)
    

    Is there anything that needs to be imported first?


  • Lifetime Qt Champion

    @Sebastian1993 You misunderstood my reply. What I meant is: you can check whether an URL is already in the list and only add it if not.


  • Lifetime Qt Champion

    @Sebastian1993 said in Remove duplicate entries from QListWidget?:

    getting red highlights there

    You should post the error...



  • @jsulm ahh I see what you mean, sorry my bad!

    here's the code I'm putting in:

        def browse_func(self):
    
            url = QFileDialog.getOpenFileNames(self, "Open a file", "", "All Files(*)::*txt",)
    
            for item in url[0]:
                if not self.list_widget.findItems(item, Qt::MatchFixedString | Qt::MatchCaseSensitive):
                self.list_widget.addItem(item)
    

    and error is simply:

    SyntaxError: invalid syntax
    

    adding a screenshot in case it helps



  • @Sebastian1993 said in Remove duplicate entries from QListWidget?:

    (item, Qt::MatchFixedString | Qt::MatchCaseSensitive)

    My bad, that bit is C++ (I used to do Python, now doing C++). You should know that will be the following in Python (you will come across C++ examples all the time):

    (item, Qt.MatchFixedString | Qt.MatchCaseSensitive)
    

    plus something like

    from PySide2.QtCore import Qt
    

    at the head of your file, which you'll need for many things Qt.

    Also (I think!) I corrected addItem(i) to addItem(item). If what you pasted is verbatim, you're missing an extra indent on that line.



  • @JonB ahh here we go it worked now! thanks a lot!

    i imported this in the beginning:

    from PyQt5.QtCore import Qt
    
    

  • Banned

    @Sebastian1993 in my experience it is far better to manipulate this data outside your ListWidget object within a much simpler list or dictionary -- and then only use the ListWidget for displaying that data as this allows you do to a lot more with that list should you need to and gives you much easier control over its contents. Thus instead of adding or not adding it to the ListWidget you can add or not add it to are python list after checking to see if it is already contained within that python list then just update the ListWidget with your python list

    Basically think of it this way the python list is the behind the scenes data table and the ListWidget is the view you present to the user -- any manipulation to the data is handled behind the scenes and the user just sees the end results -- this even goes if you allow the user to manipulate the view -- if they make changes to the view you make those changes to the behind the scenes data table and re-display the results. I think I use a model for this which allows me to just supply the entire list to the object in a one line statement



  • @Denni-0 That's exactly what I wanted initially, but I couldn't come up with the code for that. The reason is that when I'm clicking "Browse" button and selecting files, I'm adding values to the QListWidget. And if I click "Browse" again to add some more files, I have to run a check whether files are already existing in the QListWidget, which I can only do by accessing entries from QListWidet.

    If you have a solution, you're more than welcome to share it



  • @Sebastian1993
    You have chosen to use a QListWidget:

    QListWidget is a convenience class that provides a list view similar to the one supplied by QListView, but with a classic item-based interface for adding and removing items. QListWidget uses an internal model to manage each QListWidgetItem in the list.

    For a more flexible list view widget, use the QListView class with a standard model.

    It has its own internal model, and you have to use that. This approach will require copying data between its model and a representation you might make in your own code, where as @Denni-0 says you may prefer to do your list manipulation.

    If you used a QListView you could set its model to, say, a QStringListModel. That is within the Qt domain. Or, you could supply a custom model and behaviour in Python code.


  • Banned

    Yes @Sebastian1993 I have numerous solutions ;) I teach python-qt online for free however it would be more efficient for me if you would post a MUC/MRE (Minimal Usable Code example / Minimal Reproducible Example) of your code and let me look at what you are doing and help you adjust that to do what I suggested while trying to keep most of what you have


Log in to reply