简体   繁体   中英

pythonic way of replacing the content of list of list?

The code below generates unique combinations:

from itertools import permutations 

comb3 = permutations([1,1,1,0,0,0] , 3) 

def removeDuplicates(listofElements):

    # Create an empty list to store unique elements
    uniqueList = []

    # Iterate over the original list and for each element
    # add it to uniqueList, if its not already there.
    for elem in listofElements:        
        elif elem not in uniqueList:
            uniqueList.append(elem)

    # Return the list of unique elements        
    return uniqueList

comb3 = removeDuplicates(comb3)

for i in list(comb3):     
    print(i)

Intermediate Output

The result output is a list of tuples. It will be interpreted as A, B, C , 1 = EXIST , 0 = NOT EXIST .

(1, 1, 1)
(1, 1, 0)
(1, 0, 1)
(1, 0, 0)
(0, 1, 1)
(0, 1, 0)
(0, 0, 1)
(0, 0, 0)

convert to list of lists

Convert lists of tuples to a list of lists and replace its contents

res = [list(ele) for ele in comb3] 

for i in list(res):   

    if(i[0] == 1):
        i[0] = 'A Exist'

    if(i[0] == 0):
        i[0] = 'A Not Exist'

    if(i[1] == 1):
        i[1] = 'B Exist'

    if(i[1] == 0):
        i[1] = 'B Not Exist'

    if(i[2] == 1):
        i[2] = 'C Exist'

    if(i[2] == 0):
        i[2] = 'C Not Exist'

Display results

for i in list(res):   
    print(i)

Final Output

['A Exist', 'B Exist', 'C Exist']
['A Exist', 'B Exist', 'C Not Exist']
['A Exist', 'B Not Exist', 'C Exist']
['A Exist', 'B Not Exist', 'C Not Exist']
['A Not Exist', 'B Exist', 'C Exist']
['A Not Exist', 'B Exist', 'C Not Exist']
['A Not Exist', 'B Not Exist', 'C Exist']
['A Not Exist', 'B Not Exist', 'C Not Exist']

Is there a more elegant or better way of replacing the contents of a list of list?

>>> names = ['A', 'B', 'C']
>>> verbs = [' Not Exist', ' Exist']
>>> [[names[n] + verbs[v] for n, v in enumerate(c)] for c in comb3]
[['A Exist', 'B Exist', 'C Exist'],
 ['A Exist', 'B Exist', 'C Not Exist'],
 ['A Exist', 'B Not Exist', 'C Exist'],
 ['A Exist', 'B Not Exist', 'C Not Exist'],
 ['A Not Exist', 'B Exist', 'C Exist'],
 ['A Not Exist', 'B Exist', 'C Not Exist'],
 ['A Not Exist', 'B Not Exist', 'C Exist'],
 ['A Not Exist', 'B Not Exist', 'C Not Exist']]]

You could do something like this:

a = ("A", "B", "C")
res = [["{} {}Exist".format(x, '' if y else 'NOT ') for x, y in zip(a, sub)] for sub in comb3]

or like that:

a = ("A {}Exist", "B {}Exist", "C {}Exist")

res = [[x.format('' if sub[i] else 'NOT ') for i, x in enumerate(a)] for sub in lst]

or the most elegant of 'em all:

a = [("A Not Exist", "B Not Exist", "C Not Exist"), ("A Exist", "B Exist", "C Exist")]

res = [[a[x][i] for i, x in enumerate(sub)] for sub in lst]

and they all return:

print(res) # -> [['A Exist', 'B Exist', 'C Exist'], 
               # ['A Exist', 'B Exist', 'C NOT Exist'], 
               # ['A Exist', 'B NOT Exist', 'C Exist'], 
               # ['A Exist', 'B NOT Exist', 'C NOT Exist'], 
               # ['A NOT Exist', 'B Exist', 'C Exist'], 
               # ['A NOT Exist', 'B Exist', 'C NOT Exist'], 
               # ['A NOT Exist', 'B NOT Exist', 'C Exist'], 
               # ['A NOT Exist', 'B NOT Exist', 'C NOT Exist']]

You can use set to remove duplicates from a list.

Then map them to list

from itertools import permutations
import string
from pprint import pprint
alphabet = string.ascii_uppercase
comb3 = permutations([1,1,1,0,0,0] , 3)


comb3 = list(map(list,set(comb3)))


for i in comb3:
    for index, value in enumerate(i):
        i[index] = f'{alphabet[index]}{ " Not " if value>0 else " "}Exists'

pprint(comb3)

output

 [['A Not Exists', 'B Not Exists', 'C Exists'],
 ['A Exists', 'B Not Exists', 'C Not Exists'],
 ['A Exists', 'B Not Exists', 'C Exists'],
 ['A Not Exists', 'B Exists', 'C Exists'],
 ['A Exists', 'B Exists', 'C Not Exists'],
 ['A Not Exists', 'B Exists', 'C Not Exists'],
 ['A Exists', 'B Exists', 'C Exists'],
 ['A Not Exists', 'B Not Exists', 'C Not Exists']]

You can do all of these just in 2 line:

comb3 = list(set(permutations([1,1,1,0,0,0] , 3))) # set will remove duplicates automatically
result = [[f"{i} {'' if j else 'NOT '}Exist" for i, j in zip(["A", "B", "C"], k)] for k in comb3]

result will be:

[['A Exist', 'B Exist', 'C NOT Exist'],
 ['A NOT Exist', 'B Exist', 'C Exist'],
 ['A NOT Exist', 'B Exist', 'C NOT Exist'],
 ['A Exist', 'B NOT Exist', 'C NOT Exist'],
 ['A NOT Exist', 'B NOT Exist', 'C Exist'],
 ['A Exist', 'B NOT Exist', 'C Exist'],
 ['A NOT Exist', 'B NOT Exist', 'C NOT Exist'],
 ['A Exist', 'B Exist', 'C Exist']]

Note that:

f'' works with python3.6 or higher.

First, it's inefficient to use permutations and then filter them out. What you're looking for is a cartesian product. Using itertools.product with a repeat argument, you can get your desired intermediate output.

from itertools import product
comb3 = list(product([1,0], repeat=3))
#Output:
[(1, 1, 1),
 (1, 1, 0),
 (1, 0, 1),
 (1, 0, 0),
 (0, 1, 1),
 (0, 1, 0),
 (0, 0, 1),
 (0, 0, 0)]

From this point: You can use iteration and a mapping to cleanly get your desired output as follows.

column_names = 'ABC' #To map all names with the number of items. We can think of these as column names.
code_mapping = {0: 'Not Exist', 1: 'Exist'} #For mapping the codes to meanings.

output = []
for item in comb3:
    row = [f"{name} {code_mapping[code]}" for name, code in zip(column_names, item)]
    output.append(row)
print(output)

Output:

[['A Exist', 'B Exist', 'C Exist'],
 ['A Exist', 'B Exist', 'C Not Exist'],
 ['A Exist', 'B Not Exist', 'C Exist'],
 ['A Exist', 'B Not Exist', 'C Not Exist'],
 ['A Not Exist', 'B Exist', 'C Exist'],
 ['A Not Exist', 'B Exist', 'C Not Exist'],
 ['A Not Exist', 'B Not Exist', 'C Exist'],
 ['A Not Exist', 'B Not Exist', 'C Not Exist']]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM