How to add specific elements from list of lists? - python

Let's say I have the following list that contains other lists:
episodes = [
['1', '2', '3', '4', '5', '6', '7'],
['1', '2', '3', '4', '5', '1', '2', '3', '4', '5', '6'],
['1', '2', '3', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '1', '2', '3']
]
Each list refer to episodes of TV-shows. For example, the first list has one season with 7 episodes, whereas the last list has five seasons with season one having 3 episodes, season 2 6 episodes and so on. I would like to save the total number of episodes for each TV-show by adding the total number of episodes for each season of the TV-show. In other words, first list is just taking the last element of that list, but the last list I have to add 3 & 6 & 6 & 4 & 3.
I hope you understand what I'm trying to do. I thought about using indexing and see where the element '1' lies in each list with more than one season so I can choose the element before (number of episodes of previous season) and so on. But it gets a bit tricky doing it for all other seasons as well.

if you just want the total number of episodes regardless of seasons just count the length of the each show list.
episodes = [
['1', '2', '3', '4', '5', '6', '7'],
['1', '2', '3', '4', '5', '1', '2', '3', '4', '5', '6'],
['1', '2', '3', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '1', '2', '3']
]
print(*[len(show) for show in episodes], sep="\n")
OUTPUT
7
11
22

If I understand you correctly you can just sum up the length of each list, i.e. sum(map(len, episodes))?

I came up with something like this to check for number of episodes in each season:
episodes = [
['1', '2', '3', '4', '5', '6', '7', "8", "9", "10", "11"],
['1', '2', '3', '4', '5',
'1', '2', '3', '4', '5', '6'],
['1', '2', '3',
'1', '2', '3', '4', '5', '6',
'1', '2', '3', '4', '5', '6',
'1', '2', '3', '4',
'1', '2', '3']
]
def count_episodes(list_of_episodes):
all_episodes = [e for l in list_of_episodes for e in l]
previous_episode = 0
season = 1
seasons = {}
tmp_list = []
for i in all_episodes:
if previous_episode > int(i):
seasons["season "+str(season)] = tmp_list
tmp_list = []
season += 1
previous_episode = int(i)
tmp_list.append(i)
if len(tmp_list) > 0:
seasons["season "+str(season)] = tmp_list
for i in seasons:
print(i + " has {} episodes".format(len(seasons[i])))
count_episodes(episodes)
OUTPUT
season 1 has 11 episodes
season 2 has 5 episodes
season 3 has 6 episodes
season 4 has 3 episodes
season 5 has 6 episodes
season 6 has 6 episodes
season 7 has 4 episodes
season 8 has 3 episodes

simpler solution
At the end, it is sth as simple as:
list(map(len, episodes))
## [7, 11, 22]
If all episodes are listed always, then you can just count the total number of episodes - it will be always the same as if you determined the maximum numbers and summed them up.
slighlty more elaborate solution
from functools import reduce
def list_to_max_seasons(lst, first_element='1'):
return reduce(lambda l, x: l + [x] if x == first_element else l[:-1] + [x], lst, [])
def sum_max_episodes(lol):
return [(lambda l: sum([int(x) for x in l]))(list_to_max_seasons(il)) for il in lol]
Test by:
sum_max_episodes(episodes)
## [7, 11, 22]
more elaborate (recursive) solution
These solutions are not very pythonic, I admit.
But they are quite universal.
def list_to_seasons(l, acc=[], by='1', tmp=[]):
if l == []:
return acc+[tmp]
elif l[0] == by:
if tmp == []:
return list_to_seasons(l[1:], acc=[], by=by, tmp=[l[0]])
else:
return list_to_seasons(l[1:], acc=acc+[tmp], by=by, tmp=[l[0]])
else:
return list_to_seasons(l[1:], acc=acc, by=by, tmp=tmp+[l[0]])
list_to_seasons(['1','2','3','1','2','1','2','3','1','1'])
## [['1', '2', '3'], ['1', '2'], ['1', '2', '3'], ['1'], ['1']]
Or:
def list_to_max_seasons(l, acc=[], by='1', last=None):
if l == []:
return acc+[last]
elif l[0] == by:
if last is None:
return list_to_max_seasons(l[1:], acc=[], by=by, last=l[0])
else:
return list_to_max_seasons(l[1:], acc=acc+[last], by=by, last=l[0])
else:
return list_to_max_seasons(l[1:], acc=acc, by=by, last=l[0])
list_to_max_seasons(['1','2','3','1','2','1','2','3','1','1'])
## ['3', '2', '3', '1', '1']
Then:
def sum_max_episodes(lol):
return [(lambda l: sum([int(x) for x in l]))(list_to_max_seasons(il)) for il in lol]
Test by:
sum_max_episodes(episodes)
## [7, 11, 22]

Related

How to count the number of separate regions in python array

I need to count the number of separate regions in an array.
An example array is below. I can count the number of unique strings but if there are two distinct islands like in the grid below where 64733 is in the upper left and bottom right my function won't properly count the number of regions.
Can anyone help me to find a way to count the number of regions if two of the regions are comprised of the same numbers? Im writing in python 2.x.
|64733|20996|92360|92360|04478|04478|04478|04478|04478|98101
|64733|92360|92360|92360|04478|04478|04478|04478|04478|04478
|64733|92360|29136|92360|04478|04478|04478|04478|04478|04478
|64733|92360|29136|92360|04478|04478|04478|04478|04478|04478
|92360|92360|92360|92360|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|64773
|04478|04478|04478|04478|04478|04478|04478|04478|64773|64773
The input is a 3d array and looks like
[[['6', '4', '7', '3', '3'],
['2', '0', '9', '9', '6'],
['9', '2', '3', '6', '0'],
['9', '2', '3', '6', '0'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['9', '8', '1', '0', '1']],
[['6', '4', '7', '3', '3'],
['9', '2', '3', '6', '0'],
['9', '2', '3', '6', '0'],
['9', '2', '3', '6', '0'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8']],
[['6', '4', '7', '3', '3'],
['9', '2', '3', '6', '0'],
This is not the complete input (because it was huge) but it gets the point across i think
So would be where any unique symbol string of numbers lies and the total number of adjacent strings that are identical (adjacent being up down left right, not diagonal).
enter code here
You didn't post your full array, so I made some assumptions about the original pip separated value you gave us. I've written this in Python 3, but I think it should work in Python 2 only modifying the print function calls to statements.
arr = [["64733","20996","92360","92360","04478","04478","04478","04478","04478","98101"],
["64733","92360","92360","92360","04478","04478","04478","04478","04478","04478"],
["64733","92360","29136","92360","04478","04478","04478","04478","04478","04478"],
["64733","92360","29136","92360","04478","04478","04478","04478","04478","04478"],
["92360","92360","92360","92360","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","64773"],
["04478","04478","04478","04478","04478","04478","04478","04478","64773","64773"]]
x = len(arr)
y = len(arr[0])
#create a new array the same size as the original
regions = [[None for _ in range(y)] for _ in range(x)]
print(regions)
label = 0
queue = []
def check_neighbor(i, j, v):
if not regions[i][j] and arr[i][j] == v:
regions[i][j] = label
queue.insert(0, (i, j))
for i in range(x):
for j in range(y):
#don't check an already labelled region
if regions[i][j]: continue
label += 1 #new label
regions[i][j] = label
queue = [(i, j)]
v = arr[i][j]
#keep checking neighbours until we run out
while queue:
(X, Y) = queue.pop()
if X > 0:
check_neighbor(X-1, Y, v)
if X < x-1:
check_neighbor(X+1, Y, v)
if Y > 0:
check_neighbor(X, Y-1, v)
if Y < y-1:
check_neighbor(X, Y+1, v)
print(regions)
print(label) # this is the number of regions

How to find all possible combinations from nested list containing list and strings?

I am trying to get all possible pattern from list like:
input_x = ['1', ['2', '2x'], '3', '4', ['5', '5x']]
As we see, it has 2 nested list ['2', '2x'] and ['5', '5x'] here.
That means all possible pattern is 4 (2 case x 2 case), the expect output is:
output1 = ['1','2' , '3', '4', '5']
output2 = ['1','2x', '3', '4', '5']
output3 = ['1','2' , '3', '4', '5x']
output4 = ['1','2x', '3', '4', '5x']
I tried to search how to, but I can not find any examples (because of I have no idea about "keyword" to search)
I think python has inner libraries/methods to handle it.
One way to achieve this is via using itertools.product. But for using that, you need to firstly wrap the single elements within your list to another list.
For example, firstly we need to convert your list:
['1', ['2', '2x'], '3', '4', ['5', '5x']]
to:
[['1'], ['2', '2x'], ['3'], ['4'], ['5', '5x']]
This can be done via below list comprehension as:
formatted_list = [(l if isinstance(l, list) else [l]) for l in my_list]
# Here `formatted_list` is containing the elements in your desired format, i.e.:
# [['1'], ['2', '2x'], ['3'], ['4'], ['5', '5x']]
Now call itertools.product on the unpacked version of the above list:
>>> from itertools import product
# v `*` is used to unpack the `formatted_list` list
>>> list(product(*formatted_list))
[('1', '2', '3', '4', '5'), ('1', '2', '3', '4', '5x'), ('1', '2x', '3', '4', '5'), ('1', '2x', '3', '4', '5x')]
If you don't want to convert your list to all sub list then
You can try something like this :
input_x = ['1', ['2', '2x'], '3', '4', ['5', '5x'],['6','6x']]
import itertools
non_li=[]
li=[]
for i in input_x:
if isinstance(i,list):
li.append(i)
else:
non_li.append(i)
for i in itertools.product(*li):
sub=non_li[:]
sub.extend(i)
print(sorted(sub))
output:
['1', '2', '3', '4', '5', '6']
['1', '2', '3', '4', '5', '6x']
['1', '2', '3', '4', '5x', '6']
['1', '2', '3', '4', '5x', '6x']
['1', '2x', '3', '4', '5', '6']
['1', '2x', '3', '4', '5', '6x']
['1', '2x', '3', '4', '5x', '6']
['1', '2x', '3', '4', '5x', '6x']

Python - TypeError: unorderable types: str() < int()

I get this error when I try to run my code. Please help, and explain what it's trying to say!
This program is meant to find a persons ballot paper vote preferences (1st, 2nd, 3rd etc) for each candidate, and remove their first preference. That first preference is replaced by 99999, to make it easier for me.
Error:
ERROR CODE: minIndex = int(vote.index(min(vote)))
TypeError: unorderable types: str() < int()
Code:
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = 99999
return candidatePreferences
Value of vList (after calling countVotes function first time):
[[99999, '3', '4', '5', '2'], ['4', '2', '5', '3', 99999], [99999, '3', '2', '5', '4'], [99999, '2', '4', '3', '5'], [99999, '3', '4', '5', '2'], ['2', 99999, '3', '5', '4'], [99999, '3', '4', '5', '2'], ['3', '5', '2', '4', 99999], [99999, '4', '5', '2', '3'], ['5', 99999, '4', '3', '2'], ['3', '2', '5', '4', 99999], ['3', 99999, '2', '5', '4'], ['2', '5', 99999, '4', '3'], ['3', '2', 99999, '4', '5'], ['4', '5', '3', 99999, '2'], [99999, '5', '4', '3', '2'], [99999, '5', '3', '4', '2'], ['2', 99999, '4', '3', '5'], ['4', 99999, '2', '5', '3']]
Calling the function (second time):
cp = countVotes(vList)
minIndex = int(vote.index(min(vote)))
TypeError: unorderable types: str() < int()
Python cannot order str values and int values together.
In your example 99999 is an int value while all the other values are str values.
I think is this line minIndex = int(vote.index(min(vote)))
You are trying to find min on a string list. so what you can
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
vote = map(int, vote)
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = 99999
return candidatePreferences
After converting string list to Int list you can perform min operation.
Please check and let me know.
Try this code. it fixed the error:
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = '99999'
return candidatePreferences
vList = [['1', '3', '4', '5', '2'], ['4', '2', '5', '3', '1'], ['1', '3', '2', '5', '4'], ['1', '2', '4', '3', '5'], ['1', '3', '4', '5', '2'], ['2', '1', '3', '5', '4'], ['1', '3', '4', '5', '2'], ['3', '5', '2', '4', '1'], ['1', '4', '5', '2', '3'], ['5', '1', '4', '3', '2'], ['3', '2', '5', '4', '1'], ['3', '1', '2', '5', '4'], ['2', '5', '1', '4', '3'], ['3', '2', '1', '4', '5'], ['4', '5', '3', '1', '2'], ['1', '5', '4', '3', '2'], ['1', '5', '3', '4', '2'], ['2', '1', '4', '3', '5'], ['4', '1', '2', '5', '3']]
cp = countVotes(vList)
print(str(cp))
output:
[0, 4, 0, 0, 0, 1, 0, 4, 0, 1, 4, 1, 2, 2, 3, 0, 0, 1, 1]
Convert string elements to integer.You can use python map function to convert all the list elements to integer
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
vote = list(map(int, vote)) # add this line to the code to convert string elements to integer
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = 99999
return candidatePreferences

How to check columns and subgrids (Sudoku Checker in Python)?

I'm doing the traditional "Sudoku Puzzle Checker" activity, and I've only been able to figure out how to check the rows so far. As per instruction, I'm suppose to check (in 3 separate functions), the rows, columns, and subgrids (the 3x3 squares) of a solved sudoku puzzle (given in a .csv file). I understand how to do the columns (add 9 each time, 9 times starting numbers ranging from 0-8) and the subgrids (range of 3 numbers, add 6 to get to the next range of 3 numbers e.t.c) but I'm confused as how to implement these concepts into my code. Here's what I have right now:
def load_puzzle(filename):
file = open(filename, 'r')
puzzle = list(file)
#the puzzle currently looks like this:
['5,3,4,6,7,8,9,1,2\n', '6,7,2,1,9,5,3,4,8\n', '1,9,8,3,4,2,5,6,7\n', '8,5,9,7,6,1,4,2,3\n', '4,2,6,8,5,3,7,9,1\n', '7,1,3,9,2,4,8,5,6\n', '9,6,1,5,3,7,2,8,4\n', '2,8,7,4,1,9,6,3,5\n', '3,4,5,2,8,6,1,7,9\n']
print_puzzle(puzzle)
def print_puzzle(puzzle):
print(" ")
count = 0
while count <= 8:
line = list(puzzle[count])
line = [x for x in line if x != ',']
line.remove('\n')
line.insert(3, '|')
line.insert(7, '|')
if count == 3 or count == 6:
print("---------------------")
fresh = ' '.join(line)
count += 1
print('''
Checking puzzle...
''')
delimiter = ','
together = delimiter.join(puzzle)
new = list(together)
new[:] = [x for x in new if x != ',']
new[:] = [x for x in new if x != '\n']
check_rows(new)
#the puzzle now looks like this:
['5', '3', '4', '6', '7', '8', '9', '1', '2', '6', '7', '2', '1', '9', '5', '3', '4', '8', '1', '9', '8', '3', '4', '2', '5', '6', '7', '8', '5', '9', '7', '6', '1', '4', '2', '3', '4', '2', '6', '8', '5', '3', '7', '9', '1', '7', '1', '3', '9', '2', '4', '8', '5', '6', '9', '6', '1', '5', '3', '7', '2', '8', '4', '2', '8', '7', '4', '1', '9', '6', '3', '5', '3', '4', '5', '2', '8', '6', '1', '7', '9']
def check_numbers(numbers):
my_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
numbers.sort()
if numbers == my_list:
return True
else:
return False
def check_rows(n):
count = 0
start = 0
while count <= 8:
row = n[start:(start + 9)]
if check_numbers(row) is True:
count += 1
start += 9
elif check_numbers(row) is False:
break
if count == 9:
print("Rows okay...")
else:
print("Error in row", count)
check_columns(n)
def check_columns(n):
count = 0
start = 0
while count <= 8:
col = n[start::9]
if check_numbers(col) is True:
count += 1
start += 1
elif check_numbers(col) is False:
break
if count == 9:
print("Columns okay...")
else:
print("Error in row", count)
def check_subgrids(n):
filename = input("Enter file name of solved sudoku puzzle: ")
load_puzzle(filename)
I'm looking for a way to find the columns and subgrids similar to how I found the rows (i.e. row = n[start:(start + 9)]) if that's possible. I'm a beginner, so I'm also happy to learn about different tools/ways I could improve my code!
Edit: I've solved my problem with the check_columns function (code updated) but still would appreciate some guidance for the check_subgrid function!

Calculating element with most occurrences in list

I have
dict = {
0: ['9', '3', '3', '5', '1'],
1: ['9', '4', '1', '2'],
2: ['3', '4', '1', '5', '5'],
3: ['4', '4', '5', '5', '1'],
4: ['2', '8', '9', '5', '1']
}
take an example 0:['9', '3', '3', '5', '1'] here 3 has more number of occurance so iw ant to update enter list with only 3 so at index 0 becomes [3]
if every element has equal weight like 1: ['9', '4', '1', '2'] there will be no change
another ['4', '4', '5', '5', '1'] returns ['4','5']
i tried using collection.counter but donot know how to update the original dict with max repeated
for i,j in dictonary.items():
dictonary[i]=Counter(j)
expected output:
{0: ['3'], 1: ['9', '4', '1', '2'], 2: ['5'], 3: ['4'], 4: ['2', '8', '9', '5', '1']}
Edit: the list size may vary
[1,1,1,1,1,2,2,2,2,2,3,3,3]->[1,2]
[3,3,3,3,4,4,4,4,4,5,6,6,6,6,6]->[4,6]
from collections import *
d ={0: ['9', '3', '3', '5', '1'], 1: ['9', '4', '1', '2'], 2: ['3', '4', '1', '5', '5'], 3: ['4', '5', '0', '4', '3'], 4: ['2', '8', '9', '5', '1']}
for i,j in d.items():
c = Counter(j)
top = c.most_common(1)
if top[0][1] > 1:
d[i] = [ top[0][0] ]
print d
{0: ['3'], 1: ['9', '4', '1', '2'], 2: ['5'], 3: ['4'], 4: ['2', '8', '9', '5', '1']}
EDIT:
from collections import *
d = {
0: ['4', '4', '5', '5', '1'],
1: ['9', '4', '1', '2'],
2: ['3', '4', '1', '5', '5']
}
for i,j in d.items():
c = Counter(j)
result = []
for x in c:
if c[x] > 1:
result.append(x)
if result:
d[i] = result
print d
{0: ['5', '4'], 1: ['9', '4', '1', '2'], 2: ['5']}
EDIT:
from collections import *
d = {
0: ['4', '4', '5', '5', '1'],
1: [1,1,1,1,1,2,2,2,2,2,3,3,4],
2: ['3', '4', '1', '5', '5']
}
for i,j in d.items():
c = Counter(j)
longest = c.most_common(1)[0][1]
if longest > 1:
result = []
for x in c:
if c[x] == longest:
result.append(x)
d[i] = result
print d
{0: ['5', '4'], 1: [1, 2], 2: ['5']}
It appears you're looking for the mode of each element in your dictionary.
from collections import Counter
def mode(L):
result = []
for x in L:
if Counter(L)[x] == max(Counter(L).values()):
if x not in result: result.append(x)
return result
for item in dict:
dict[item] = mode(dict[item])

Categories