Replace first elements of tuple with zero over a certain length - python

I have a sorted list based on first element:
A = [(0.11, '201405'), (0.41, '201402'),.....,(1.5, '201430')] # values and time
and want to change first element of each tuple:
x = len(C) # C is a list and its length is 2
y = len(D) # D is a list and its length is 1
if x > y:
A[0[0:x]] = 0.0 # if x > y then set first element of A equal to zero (over length of C)
But I get following error:
TypeError: 'int' object is not subscriptable
Please suggest to fix it.

If I understand your question correctly, you want to replace the first element in each of the first few tuples with 0. Tuples are not modifyable, so you can not modify the existing tuples in the list, but you have to create a new list, holding new tuples. You can do this using a list comprehension.
Example:
>>> A = [(1,"a"), (2,"b"), (3,"c"), (4,"d")]
>>> A = [(x if i > 1 else 0, y) for i, (x, y) in enumerate(A)]
>>> print A
[(0, 'a'), (0, 'b'), (3, 'c'), (4, 'd')]
This will enumerate all the entries in the list, and for each entry create a tuple with the first element being 0, if the index i of that entry is lower than some threshold, or the original value otherwise.

As iharob mentioned, you have a subscript notation error.
Tuples are immutable. You can't just replace 1 element of the tuple in your list. You have to replace the whole tuple with another tuple containing 0.0 as first value and the existing second value. Note that lists are modifiable but tuples aren't. That's why you can update the list A, but you have to replace the tuple with a new tuple.
Here's an example that does not recreate the whole list:
for i, t in enumerate(A):
if i < 1:
A[i] = (0, t[1])

You have an error in A[0[0:x]] = 0.0 you are using subscript notation for the number 0.

Furthermore, the tuple is an immutable type. Hence, it is impossible to change the content of a tuple. You'd better to generate a new list such as:
A = [0.0]+A[1:]

Related

How does this python enumerate script work and what makes it so fast? [duplicate]

What does for row_number, row in enumerate(cursor): do in Python?
What does enumerate mean in this context?
The enumerate() function adds a counter to an iterable.
So for each element in cursor, a tuple is produced with (counter, element); the for loop binds that to row_number and row, respectively.
Demo:
>>> elements = ('foo', 'bar', 'baz')
>>> for elem in elements:
... print elem
...
foo
bar
baz
>>> for count, elem in enumerate(elements):
... print count, elem
...
0 foo
1 bar
2 baz
By default, enumerate() starts counting at 0 but if you give it a second integer argument, it'll start from that number instead:
>>> for count, elem in enumerate(elements, 42):
... print count, elem
...
42 foo
43 bar
44 baz
If you were to re-implement enumerate() in Python, here are two ways of achieving that; one using itertools.count() to do the counting, the other manually counting in a generator function:
from itertools import count
def enumerate(it, start=0):
# return an iterator that adds a counter to each element of it
return zip(count(start), it)
and
def enumerate(it, start=0):
count = start
for elem in it:
yield (count, elem)
count += 1
The actual implementation in C is closer to the latter, with optimisations to reuse a single tuple object for the common for i, ... unpacking case and using a standard C integer value for the counter until the counter becomes too large to avoid using a Python integer object (which is unbounded).
It's a builtin function that returns an object that can be iterated over. See the documentation.
In short, it loops over the elements of an iterable (like a list), as well as an index number, combined in a tuple:
for item in enumerate(["a", "b", "c"]):
print item
prints
(0, "a")
(1, "b")
(2, "c")
It's helpful if you want to loop over a sequence (or other iterable thing), and also want to have an index counter available. If you want the counter to start from some other value (usually 1), you can give that as second argument to enumerate.
I am reading a book (Effective Python) by Brett Slatkin and he shows another way to iterate over a list and also know the index of the current item in the list but he suggests that it is better not to use it and to use enumerate instead.
I know you asked what enumerate means, but when I understood the following, I also understood how enumerate makes iterating over a list while knowing the index of the current item easier (and more readable).
list_of_letters = ['a', 'b', 'c']
for i in range(len(list_of_letters)):
letter = list_of_letters[i]
print (i, letter)
The output is:
0 a
1 b
2 c
I also used to do something, even sillier before I read about the enumerate function.
i = 0
for n in list_of_letters:
print (i, n)
i += 1
It produces the same output.
But with enumerate I just have to write:
list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
print (i, letter)
As other users have mentioned, enumerate is a generator that adds an incremental index next to each item of an iterable.
So if you have a list say l = ["test_1", "test_2", "test_3"], the list(enumerate(l)) will give you something like this: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].
Now, when this is useful? A possible use case is when you want to iterate over items, and you want to skip a specific item that you only know its index in the list but not its value (because its value is not known at the time).
for index, value in enumerate(joint_values):
if index == 3:
continue
# Do something with the other `value`
So your code reads better because you could also do a regular for loop with range but then to access the items you need to index them (i.e., joint_values[i]).
Although another user mentioned an implementation of enumerate using zip, I think a more pure (but slightly more complex) way without using itertools is the following:
def enumerate(l, start=0):
return zip(range(start, len(l) + start), l)
Example:
l = ["test_1", "test_2", "test_3"]
enumerate(l)
enumerate(l, 10)
Output:
[(0, 'test_1'), (1, 'test_2'), (2, 'test_3')]
[(10, 'test_1'), (11, 'test_2'), (12, 'test_3')]
As mentioned in the comments, this approach with range will not work with arbitrary iterables as the original enumerate function does.
The enumerate function works as follows:
doc = """I like movie. But I don't like the cast. The story is very nice"""
doc1 = doc.split('.')
for i in enumerate(doc1):
print(i)
The output is
(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
I am assuming that you know how to iterate over elements in some list:
for el in my_list:
# do something
Now sometimes not only you need to iterate over the elements, but also you need the index for each iteration. One way to do it is:
i = 0
for el in my_list:
# do somethings, and use value of "i" somehow
i += 1
However, a nicer way is to user the function "enumerate". What enumerate does is that it receives a list, and it returns a list-like object (an iterable that you can iterate over) but each element of this new list itself contains 2 elements: the index and the value from that original input list:
So if you have
arr = ['a', 'b', 'c']
Then the command
enumerate(arr)
returns something like:
[(0,'a'), (1,'b'), (2,'c')]
Now If you iterate over a list (or an iterable) where each element itself has 2 sub-elements, you can capture both of those sub-elements in the for loop like below:
for index, value in enumerate(arr):
print(index,value)
which would print out the sub-elements of the output of enumerate.
And in general you can basically "unpack" multiple items from list into multiple variables like below:
idx,value = (2,'c')
print(idx)
print(value)
which would print
2
c
This is the kind of assignment happening in each iteration of that loop with enumerate(arr) as iterable.
the enumerate function calculates an elements index and the elements value at the same time. i believe the following code will help explain what is going on.
for i,item in enumerate(initial_config):
print(f'index{i} value{item}')

Python enumerated array syntax

I'm writing in Python and writing to a console with an array I am manipulating and have a syntax question.
The array is passed in and I create another another array for tracking position using along with sort the array but I dont see why when I want to access the iterable array it becomes a 2d array
posarr = [*enumerate(arr)]
posarr.sort(key = lambda it:it[1])
Then to access from a loop it is:
posarr[i][0] == blah
instead of
posarr[i] == blah
?
It's not a 2D array, it's a list of tuples. In each tuple, the first item is the index, and the second is the value (as you would expect from enumerate).
Forget about the sorting for now, just look at what posarr contains, for example:
>>> posarr = [*enumerate('cab')]
>>> posarr
[(0, 'c'), (1, 'a'), (2, 'b')]
BTW this has nothing to do with syntax.
Note: The enumerate() function assigns an index to each item in an iterable object
So, posarr = [*enumerate(arr)] will create a new array of tuples, where the first item of the tuple will be the index and the second item be the array element at that index.
After posarr = posarr.sort(key = lambda it:it[1]), posarr will be None because list.sort() does not return anything. It sorts an array in-place.
It should be like this: posarr.sort(key = lambda it:it[1]).
posarr[i] will return the tuple at index i, so to access the element at that index, you have to do something like this posarr[i][1]. posarr[i][0] is the index of the element posarr[i][1].
So, posarr is not a 2-D array, it is just an array of tuples.

Adding 1 to Value in Dictionary

I have seen others ways of adding 1 to a value in a dictionary.
I simply keep getting an error when I try to add a value of 1 to a dictionary key value in python.
Here is my code:
arr = {('1', '20'): [0], ('15', '14'): [0]}
I want to add 1 to key ('1', '20').
Here is my code:
w = 1
x = 20
arr[(w, x)] += 1
I get the error code:
TypeError: 'int' object is not iterable
I simply do not know what I am doing wrong. Any suggestions are greatly appreciated.
Two issues:
The keys of your dictionary are tuples of strings, but you're trying to index into the dictionary using a tuple of ints.
The values in your dictionary are (1-length) lists of ints, but you're trying to add a number to one of those lists.
You might want something like this:
w = '1'
x = '20'
arr[(w, x)][0] += 1
Without seeing more of your code, it could be that you want something more like this:
# dictionary mapping tuples of ints to ints
arr = { (1, 20): 0, (15, 14): 0 }
# now we can just use ints
w = 1
x = 20
# and no need to use [0] to get the first element of the list
# (because it's no longer a list)
arr[(w, x)] += 1

how to add specific elements of a tuple

I have:
([(5,2),(7,2)],[(5,1),(7,3),(11,1)])
I need to add the second elements having the same first element.
output:[(5,3),(7,5),(11,1)]
This is a great use-case for collections.Counter...
from collections import Counter
tup = ([(5,2),(7,2)], [(5,1),(7,3),(11,1)])
counts = sum((Counter(dict(sublist)) for sublist in tup), Counter())
result = list(counts.items())
print(result)
One downside here is that you'll lose the order of the inputs. They appear to be sorted by the key, so you could just sort the items:
result = sorted(counts.items())
A Counter is a dictionary whose purpose is to hold the "counts" of bins. Counts are cleverly designed so that you can simply add them together (which adds the counts "bin-wise" -- If a bin isn't present in both Counters, the missing bin's value is assumed to be 0). So, that explains why we can use sum on a bunch of counters to get a dictionary that has the values that you want. Unfortunately for this solution, a Counter can't be instantiated by using an iterable that yields 2-item sequences like normal mappings ...,
Counter([(1, 2), (3, 4)])
would create a Counter with keys (1, 2) and (3, 4) -- Both values would be 1. It does work as expected if you create it with a mapping however:
Counter(dict([(1, 2), (3, 4)]))
creates a Counter with keys 1 and 3 (and values 2 and 4).
Try this code: (Brute force, may be..)
dt = {}
tp = ([(5,2),(7,2)],[(5,1),(7,3),(11,1)])
for ls in tp:
for t in ls:
dt[t[0]] = dt[t[0]] + t[1] if t[0] in dt else t[1]
print dt.items()
The approach taken here is to loop through the list of tuples and store the tuple's data as a dictionary, wherein the 1st element in the tuple t[0] is the key and the 2nd element t[1] is the value.
Upon iteration, every time the same key is found in the tuple's 1st element, add the value with the tuple's 2nd element. In the end, we will have a dictionary dt with all the key, value pairs as required. Convert this dictionary to list of tuples dt.items() and we have our output.

Python: List containing tuple and integer

I have a list that is a combination of a tuple and integer
ex: K = [(7,8),8]
How do I access the first element of the tuple, 7?
I tried K[0[0]] and was not successful.
Try doing the following:
>>> k = [(7,8),8]
>>> k[0]
(7, 8)
>>> k[0][0]
7
Accessing element like this in a collection is wrong -
K[0[0]]
In this case, you are indexing the 0th element of 0 itself, which definitely causes an error. Try doing k[0][0]

Categories

Resources