Try using tuple[int, ...] for your type hint for position:
from typing import Optional
def is_none(position: tuple[int, ...], board: list[list[Optional[int]]]) -> bool:
if not len(board) or not all(len(row) == len(board) for row in board):
raise ValueError('Invalid board, must be square.')
board_rows, board_cols = len(board), len(board[0])
if len(position) != 2:
raise ValueError('Position must have exactly two values.')
row, col = position
if 0 <= row < board_rows and 0 <= col < board_cols:
return board[row][col] is None
raise ValueError('Position must be on board.')
def main() -> None:
board = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 1, 2, 3],
[4, 5, 6, None],
]
print(is_none((0, 0), board))
print(is_none((3, 3), board))
if __name__ == '__main__':
main()
Output:
False
True
Answer from Sash Sinha on Stack OverflowI just typed up something quickly, maybe you get an idea from here
from datetime import datetime, date
# stores each time fram between pickup and dropoff
time = []
# inits a global counter, that is updated dependend on you array
counter = 0
# inits global time constants that are updated, based on logic
starttime = datetime(2009, 10, 5, 18, 0)
endtime = datetime(2009, 10, 5, 18, 0)
for i in range(len(s)):
# check if initial pickup, if 0 that means inital pickup, therefore update time
if(counter == 0):
starttime = datetime.strptime(s[i][1],'%Y-%m-%d %H:%M:%S')
# in case pickup add 1 to counter to indicate the number of packages on hand
if(s[i][2] == 'pickup'):
counter = counter + 1
# in case dropoff subtract 1 from counter to update packages on hand
else:
counter = counter - 1
# in case counter reaches 0 meaning no more packages, therefore measure time differences
if(counter == 0):
endtime = datetime.strptime(s[i][1],'%Y-%m-%d %H:%M:%S')
print(endtime - starttime)
time.append(endtime - starttime)
Try the below code:
from datetime import datetime
def calculateTime(frm, to):
p = '%Y-%m-%d %H:%M:%S'
epoch = datetime(1970, 1, 1)
frmTime = (datetime.strptime(frm, p) - epoch).total_seconds()
toTime = (datetime.strptime(to, p) - epoch).total_seconds()
return toTime - frmTime
def printTime(t, form='H:M'):
h = int(t/(60*60))
m = int(60 * (t/(60*60) - h))
s = int(t - ((h * 60 * 60) + (m * 60)))
if form == 'H:M':
print h,'hrs ',m,'mins'
if form == 'H:M:S':
print h,'hrs ',m,'mins',s,' secs'
#changed
def totalActiveTime(lst):
orders = []
activeTime = 0
prevTime = None
for i in lst:
if i[2] == 'pickup':
orders.append(i[0])
if prevTime == None:
prevTime = i[1]
elif i[2] == 'dropoff':
orders.remove(i[0])
if len(orders) == 0:
activeTime += calculateTime(prevTime, i[1])
prevTime = None
return activeTime
s = [
[1, '2017-08-15 13:30:00', 'pickup'],
[1, '2017-08-15 14:00:00', 'dropoff'],
[2, '2017-08-15 14:30:00', 'pickup'],
[3, '2017-08-15 14:35:00', 'pickup'],
[2, '2017-08-15 15:00:00', 'dropoff'],
[4, '2017-08-15 15:05:00', 'pickup'],
[3, '2017-08-15 15:10:00', 'dropoff'],
[4, '2017-08-15 15:40:00', 'dropoff'],
]
printTime(totalActiveTime(s))
Output
1 hrs 40 mins
An array and nested list version:
In [163]: A=np.arange(12).reshape(3,4)
In [164]: Al = A.tolist()
For sliced indexing, a list comprehension (or mapping equivalent) works fine:
In [165]: A[:,1:3]
Out[165]:
array([[ 1, 2],
[ 5, 6],
[ 9, 10]])
In [166]: [l[1:3] for l in Al]
Out[166]: [[1, 2], [5, 6], [9, 10]]
For advanced indexing, the list requires a further level of iteration:
In [167]: A[:,[0,2,3]]
Out[167]:
array([[ 0, 2, 3],
[ 4, 6, 7],
[ 8, 10, 11]])
In [169]: [[l[i] for i in [0,2,3]] for l in Al]
Out[169]: [[0, 2, 3], [4, 6, 7], [8, 10, 11]]
Again there are various mapping alternatives.
In [171]: [operator.itemgetter(0,2,3)(l) for l in Al]
Out[171]: [(0, 2, 3), (4, 6, 7), (8, 10, 11)]
itemgetter uses tuple(obj[i] for i in items) to generate those tuples.
Curiously, itemgetter returns tuples for the list index, and lists for slices:
In [176]: [operator.itemgetter(slice(1,3))(l) for l in Al]
Out[176]: [[1, 2], [5, 6], [9, 10]]
Wasteful but should work:
list(zip(*(list(zip(*A))[0:9])))
Slightly more economical using itertools.isclice:
list(zip(*(itertools.islice(zip(*A), 0, 9))))
Or one could use map and operator.itemgetter:
list(map(operator.itemgetter(slice(0,9)), A))
Use matrix = [[0 for i in range(4)] for j in range(4)] instead of matrix = [[0] * 4] * 4.
matrix = [[0 for i in range(4)] for j in range(4)]
matrix[0][0] = 1
for row in matrix:
print(row)
Output:
[1, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
I actually ran into this problem a while ago! No, this isn't the correct way, at least for what you're expecting to happen.
The problem is that when you initialise this list, you create a list of references back to the first item, so when you modify it, you modify all of them, because in reality they all point to the same object in memory.
Instead of that you can do something like this:
x = 4
y = 4
matrix = [[0]*x for _ in range(y)]
With a result of:
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
Then matrix[0][0] = 1 only sets the first element of the first list to 1.
You can extend this into 3D and beyond by simply adding a new layer of for __ in range(z) on the end and and wrapping it in more square brackets.
finalList is always an empty list on your list-comprehension even though you think it's appending during that to it, which is not the same exact case as the second code (double for loop).
What I would do instead, is use set:
>>> set(i for sub_l in x for i in sub_l)
{1, 2, 3}
EDIT: Otherway, if order matters and approaching your try:
>>> final_list = []
>>> x_flat = [i for sub_l in x for i in sub_l]
>>> list(filter(lambda x: f.append(x) if x not in final_list else None, x_flat))
[] #useless list thrown away and consumesn memory
>>> f
[1, 2, 3]
Or
>>> list(map(lambda x: final_list.append(x) if x not in final_list else None, x_flat))
[None, None, None, None] #useless list thrown away and consumesn memory
>>> f
[1, 2, 3]
EDIT2:
As mentioned by timgeb, obviously the map & filter will throw away lists that are at the end useless and worse than that, they consume memory. So, I would go with the nested for loop as you did in your last code example, but if you want it with the list comprehension approach than:
>>> x_flat = [i for sub_l in x for i in sub_l]
>>> final_list = []
>>> for number in x_flat:
if number not in final_list:
finalList.append(number)
The expression on the right-hand-side is evalueated first, before assigning the result of this list comprehension to the finalList. Whereas in your second approach you write to this list all the time between the iterations. That's the difference.
That may be similar to the considerations why the manuals warn about unexpected behaviour when writing to the iterated iterable inside a for loop.
you could use the built-in set()-method to remove duplicates (you have to do flatten() on your list before)
You could try:
[[x[1]-y[1] for y in TeamList] for x in TeamList]
That will generate a nested list representing the proposed output (without the column and row headings, of course).
Just using tabs rather than any fancy formatting to build the chart:
Team1 = ["Red", 10]
Team2 = ["Green", 5]
Team3 = ["Blue", 6]
Team4 = ["Yellow", 8]
Team5 = ["Purple", 9]
Team6 = ["Brown", 4]
TeamList = [Team1, Team2, Team3, Team4, Team5, Team6]
# print the top row of team names, tab separated, starting two tabs over:
print '\t\t', '\t'.join(team[0] for team in TeamList)
# for each row in the chart
for team in TeamList:
# put two tabs between each score difference column
scoreline = '\t\t'.join(str(team[1] - other[1]) for other in TeamList)
# and print the team name, a tab, then the score columns
print team[0], '\t', scoreline
multiplying a single reference data type would simply create multiple references of the same type. What it means is that [True]*N is actually N times the same instance of the element [True]
Thus changing one would inadvertently change the others
As you can see in the following example,
>>> grid = [[True]]*10
>>> grid = [True]*10
>>> [id(e) for e in grid]
[505379788, 505379788, 505379788, 505379788, 505379788, 505379788, 505379788, 505379788, 505379788, 505379788]
It shows all the elements are actually the same instance.
But because here as the element is not a mutable Type, changing won't be an issue here as, changing one of the element would simply assign a new instance.
Problem happens with a mutable type
>>> [id(e) for e in grid]
[66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744]
>>> grid[0][0]=False
>>> [id(e) for e in grid]
[66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744, 66523744]
>>> grid
[[False], [False], [False], [False], [False], [False], [False], [False], [False], [False]]
To get over it, you need to understand which are mutable types and refrain from duplicating it but instead create new multiple instances of the same mutable types
So here as a list is a mutable type, you need to create multiple instances, possibly through list comprehension
[[False]*N for _ in range(N)]
Much like this question, you're lists are in fact pointing to the same list. Instead, define your list as:
[[False] * N for i in xrange(N)]
Or in Python 3:
[[False] * N for i in range(N)]
Then modifying one element will modify only that element.
Note the Python 3 range function also works in Python 2 - however in Python 2 the range function returns a list, as opposed to a range object in Python 3, and the xrange object of Python 2, both of which are iterators.
You haven't declared ar yet. In Python, you don't have to perform separate declaration and initialization; nevertheless, you can't perform operations on names willy-nilly.
Start off with something like this:
ar = [[0 for j in range(m)] for i in range(n)]
You should know that ar is not defined when you are trying to perform an assignment like ar[i][j] = int(input()), there are many ways to fix that.
In C/C++
In C/C++, I presume you would do such work like this:
#include <cstdio>
int main()
{
int m, n;
scanf("%d %d", &m, &n);
int **ar = new int*[m];
for(int i = 0; i < m; i++)
ar[i] = new int[n];
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
scanf("%d", &ar[i][j]);
// Do what you want to do
for(int i = 0; i < m; i++)
delete ar[i];
delete ar;
return 0;
}
Before you get inputs by scanf in C/C++, you should allocate storage by calling new or malloc, then you can perform your scanf, or it will crash.
How to do like that in Python
It's very similar to what you had done in C/C++, according to your code, when you are trying to perform assignment to ar[i][j], Python has no idea what ar it is! So you have to let it know first.
A NOT-pythonic way
A NOT-Pythonic way is do something like you did in C/C++:
n = int(input())
m = int(input())
ar = []
for i in range(m):
ar.append([])
for j in range(n):
k = int(input())
ar[i].append(k)
for i in range(m):
for j in range(n):
print(ar[i][j])
You initialize the list by ar = [] like you did int **ar = new int*[m]; in C/C++. For each row in the 2-d list, initialize the row by using ar.append([]) like you did ar[i] = new int[n]; in C/C++. Then, get your data by using input and append it to ar[i].
A pythonic way
The way to perform such a job like above it's not very pythonic, instead, you can get it done by using a feature called List Comprehensions, then the code can be simplified into this:
n = int(input())
m = int(input())
ar = [[0 for j in range(n)] for i in range(m)]
for i in range(m):
for j in range(n):
k = int(input())
ar[i][j] = k
for i in range(m):
for j in range(n):
print(ar[i][j])
Note that the core ar = [[0 for j in range(n)] for i in range(m)] is a list comprehension that it creates a list which has m lists and for each list of these m lists it has n 0s.
To initialize a two-dimensional list in Python, use
t = [ [0]*3 for i in range(3)]
But don't use [[v]*n]*n, it is a trap!
>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
A pattern that often came up in Python was
bar = []
for item in some_iterable:
bar.append(SOME EXPRESSION)
which helped motivate the introduction of list comprehensions, which convert that snippet to
bar = [SOME_EXPRESSION for item in some_iterable]
which is shorter and sometimes clearer. Usually, you get in the habit of recognizing these and often replacing loops with comprehensions.
Your code follows this pattern twice
twod_list = [] \
for i in range (0, 10): \
new = [] \ can be replaced } this too
for j in range (0, 10): } with a list /
new.append(foo) / comprehension /
twod_list.append(new) /
You want the 1 to end element of every row in your matrix.
mylist = [[1, 2, 3, 4],
['a', 'b', 'c', 'd'],
[9, 8, 7, 6]]
new_list = [row[1:] for row in mylist]
I want explain, what have you done by this
print(list[0:][1:])
print(list[1:][0:])
Firstly note that python use indices starting at 0, i.e. for [1,2,3] there is 0th element, 1th element and 2nd element.
[0:] means get list elements starting at 0th element, this will give you copy of list, [1:] means get list elements starting at 1th element, which will give you list with all but 0th element. Therefore both lines are equivalent to each other and to
print(list[1:])
You might desired output using comprehension or map as follows
list1 = [[1, 2, 3, 4], ['a', 'b', 'c', 'd'], [9, 8, 7, 6]]
list2 = list(map(lambda x:x[1:],list1))
print(list2)
output
[[2, 3, 4], ['b', 'c', 'd'], [8, 7, 6]]
lambda here is nameless function, note that comprehension here is more readable, but might be easier to digest if you earlier worked with language which have similar feature, e.g. JavaScript's map
Since you're working with a 2D-list, it might be a good idea to use numpy. You'll then simply need to define index as a tuple. Index 3 would be out of range, though:
>>> import numpy as np
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> index = (1, 2)
>>> a[index]
6
The method you're looking for is called Array#dig in Ruby:
[[1,2,3], [4,5,6], [7,8,9]].dig(1, 2)
# 6
but I couldn't find any plain Python equivalent.
You could just create a simple function that iterates over the index. For every element in index just fetch item from object and assign that as a new object. Once you have iterated over the whole index return current object. As @EricDuminil noted it works with dicts and all other objects that support __getitem__:
def index(obj, idx):
for i in idx:
obj = obj[i]
return obj
LST = [[1,2,3], [4,[5],6], [{'foo': {'bar': 'foobar'}},8,9]]
INDEXES = [[2, 2], [1, 1, 0], [2, 0, 'foo', 'bar']]
for i in INDEXES:
print('{0} -> {1}'.format(i, index(LST, i)))
Output:
[2, 2] -> 9
[1, 1, 0] -> 5
[2, 0, 'foo', 'bar'] -> foobar
same way you did the fill in, but reverse the indexes:
>>> for j in range(columns):
... for i in range(rows):
... print mylist[i][j],
...
0,0 1,0 2,0 0,1 1,1 2,1
>>>
This is the correct way.
>>> x = [ ['0,0', '0,1'], ['1,0', '1,1'], ['2,0', '2,1'] ]
>>> for i in range(len(x)):
for j in range(len(x[i])):
print(x[i][j])
0,0
0,1
1,0
1,1
2,0
2,1
>>>
length = sum([len(arr) for arr in mylist])
sum([len(arr) for arr in mylist[0:3]]) = 9
sum([len(arr) for arr in mylist[1:3]]) = 6
sum([len(arr) for arr in mylist[2:3]]) = 3
Sum the length of each list in mylist to get the length of all elements.
This will only work correctly if the list is 2D. If some elements of mylist are not lists, who knows what will happen...
Additionally, you could bind this to a function:
len2 = lambda l: sum([len(x) for x in l])
len2(mylist[0:3]) = 9
len2(mylist[1:3]) = 6
len2(mylist[2:3]) = 3
You can flatten the list, then call len on it:
>>> mylist=[[1,2,3],[4,5,6],[7,8,9]]
>>> import collections
>>> def flatten(l):
... for el in l:
... if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
... for sub in flatten(el):
... yield sub
... else:
... yield el
...
>>> len(list(flatten(mylist)))
9
>>> len(list(flatten(mylist[1:3])))
6
>>> len(list(flatten(mylist[0:1])))
3
Simple, use + operator. You could concatenate two lists using + operator.
>>> list1 = [('a', '1'), ('b', '2'), ('c', '3')]
>>> list2 = [('d', '4'), ('e', '5'), ('f', '6')]
>>> list2 + list1
[('d', '4'), ('e', '5'), ('f', '6'), ('a', '1'), ('b', '2'), ('c', '3')]
You can use extend to modify list2 inplace:
>>> list2.extend(list1)
>>> list2
[('d', '4'), ('e', '5'), ('f', '6'), ('a', '1'), ('b', '2'), ('c', '3')]
This is particularly efficient if you're extending a large list, since no copy of that list is made: the operation is O(k) in complexity, where k is the length of the list you're adding on.
This is essentially the same behaviour as the code in your question that, as others have pointed out, should work. In practice extend should be a little faster because the loop over list1 is moved down to C level.
ValueError: too many values to unpack indicates that one or more of the tuples in your list final_list has more than two elements. This causes the line for x, y in final_list: to raise the error since x and y can't label every element in the tuple.