Search code examples
pythonindexingsublist

Printing all sublists with a reoccurring item in the same index


Data = [ [0, 'Dev', 'Test1', 0, 0], [0, 'Dev', 'Test2', 0, 0], [0, 'Dev', 'Test3', 0, 0]
          ]

loop = 1
while loop == 1:
#There Is more than one user, they can only see their data
    print ('type name of User')
    User = str(input())

This is where the problem resides. The challenge is printing out every occurrence of the user that is being used when in the first Index.

try:
    YP = (Data[[value[1] for value in Data].index(User)][2])
    print ('|['+User+'][', YP)
except ValueError:
    print ('No Data')
                

We want an output like this using Dev:

|[Dev][ Test 1
|[Dev][ Test 2
|[Dev][ Test 3

And we want an output like this using other names:

No Data

But when new data is entered for this other name:

|[Ck][ Hello
|[Ck][ Konichiwa
|[Ck][ Bonjour  

This is how new data is entered:

print ('Type = New Data')
NewData = str(input())

PID = len(Data)
PID = (PID - 1)
PID = Data[PID] [0]
PID = (PID + 1)
Data.append([PID, User, NewData, 0, 0])
print (Data)

Solution

  • YP = (Data[[value[1] for value in Data].index(User)][2])
    

    index() only returns 1 value, the first value it finds, so this line will only ever give you 1 value. Since you want to print all values, you do need a for cycle.

    This line is also very hard to read, since it's trying to do a lot at the same time. Don't be afraid to use more lines of code as it often increases the readability of your code.

    The first thing i would do is filter the initial data to only get the records that are for the User:

    UserData = list(filter(lambda x: x[1] == User, Data)) 
    

    This returns the same list as Data, but only the records which have its index 1 equal to our User. If you are using Python 2, list(...) is unnecessary since filter() already returns a list. But in Python 3 it returns a filter object and we do need to convert it to a list.

    If this new list has no elements, there was no data for the user. If it has some elements, we iterate over them and print them:

    if len(UserData) > 0:
        for data in UserData:
            value = data[2]
            print(f'][{User}][ {value}')
    else:
        print('No data')
    

    Checking the length of our filtered list to know if we have data is cleaner than relying on an exception to do it for us. Here i'm using f-strings to print the data. You could also use the more traditional format() function if you feel more comfortable:

    print('][{}][ {}'.format(User, value))
    

    The complete code looks like:

    UserData = list(filter(lambda x: x[1] == User, Data))
    
    if len(UserData) > 0:
        for data in UserData:
            value = data[2]
            print(f'][{User}][ {value}')
    else:
        print('No data')