J'onn J'onzz
J'onn J'onzz

Reputation: 557

ValueError: max() arg is an empty sequence

I've created a GUI using wxFormBuilder that should allow a user to enter the names of "visitors to a business" into a list and then click one of two buttons to return the most frequent and least frequent visitors to the business.

I created an earlier version that, unfortunately, gave me the range of visitors, rather than the name of the most/least frequent visitor. I've attached a screenshot of the GUI I've created to help add a little clarity to the issue ( https://i.sstatic.net/6GHbK.jpg ).

A new code version takes a different tack than the earlier version, and I can't get it to throw anything. Instead, I keep receiving this error:

ValueError: max() arg is an empty sequence

In relation to this line:

self.txtResults.Value = k.index(max(v))

import wx
import myLoopGUI
import commands

class MyLoopFrame(myLoopGUI.MyFrame1):
    def __init__(self, parent):
        myLoopGUI.MyFrame1.__init__(self, parent)

    def clkAddData(self,parent):
        if len(self.txtAddData.Value) != 0:
            try:
                myname = str(self.txtAddData.Value)
                self.listMyData.Append(str(myname))
            except:
                wx.MessageBox("This has to be a name!")            
        else:
            wx.MessageBox("This can't be empty")




    def clkFindMost(self, parent):
        self.listMyData = []
        unique_names = set(self.listMyData)
        frequencies = {}
        for name in unique_names:
            if frequencies.get[name]:
                frequencies[name] += 1
            else:
                frequencies[name] = 0

        v = list(frequencies.values())
        k = list(frequencies.keys())
        self.txtResults.Value = k.index(max(v))


    def clkFindLeast(self, parent):
        unique_names = set(self.listMyData)
        frequencies = {}
        for name in unique_names:
            if frequencies.get(name):
                frequencies[name] += 1
            else:
                frequencies[name] = 0

        v = list(frequencies.values())
        k = list(frequencies.keys())
        self.txtResults.Value = k.index(min(v))

myApp = wx.App(False)
myFrame = MyLoopFrame(None)
myFrame.Show()
myApp.MainLoop()

Upvotes: 53

Views: 206218

Answers (5)

Ravi Bandoju
Ravi Bandoju

Reputation: 918

Pass a default value which can be returned by max if the sequence is empty:

max(v, default=0)

Upvotes: 75

djdebonis
djdebonis

Reputation: 1

I realized that I was iterating over a list of lists where some of them were empty. I fixed this by adding this preprocessing step:

tfidfLsNew = [x for x in tfidfLs if x != []]

the len() of the original was 3105, and the len() of the latter was 3101, implying that four of my lists were completely empty. After this preprocess my max() min() etc. were functioning again.

Upvotes: 0

Mohideen bin Mohammed
Mohideen bin Mohammed

Reputation: 20137

in one line,

v = max(v) if v else None

>>> v = []
>>> max(v)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence
>>> v = max(v) if v else None
>>> v
>>> 

Upvotes: 7

Aamish Baloch
Aamish Baloch

Reputation: 1200

When the length of v will be zero, it'll give you the value error.

You should check the length or you should check the list first whether it is none or not.

if list:
    k.index(max(list))

or

len(list)== 0

Upvotes: 7

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250901

Since you are always initialising self.listMyData to an empty list in clkFindMost your code will always lead to this error* because after that both unique_names and frequencies are empty iterables, so fix this.

Another thing is that since you're iterating over a set in that method then calculating frequency makes no sense as set contain only unique items, so frequency of each item is always going to be 1.

Lastly dict.get is a method not a list or dictionary so you can't use [] with it:

Correct way is:

if frequencies.get(name):

And Pythonic way is:

if name in frequencies:

The Pythonic way to get the frequency of items is to use collections.Counter:

from collections import Counter   #Add this at the top of file.

def clkFindMost(self, parent):

        #self.listMyData = []   
        if self.listMyData:
           frequencies = Counter(self.listMyData)
           self.txtResults.Value = max(frequencies, key=frequencies.get)
        else:
           self.txtResults.Value = '' 

max() and min() throw such error when an empty iterable is passed to them. You can check the length of v before calling max() on it.

>>> lst = []
>>> max(lst)

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    max(lst)
ValueError: max() arg is an empty sequence
>>> if lst:
    mx = max(lst)
else:
    #Handle this here

If you are using it with an iterator then you need to consume the iterator first before calling max() on it because boolean value of iterator is always True, so we can't use if on them directly:

>>> it = iter([])
>>> bool(it)
True
>>> lst = list(it)
>>> if lst:
       mx = max(lst)
    else:
      #Handle this here   

Good news is starting from Python 3.4 you will be able to specify an optional return value for min() and max() in case of empty iterable.

Upvotes: 19

Related Questions