I would like to add an item to a list in python, I want to add the item at an index which is greater than the size of the list. This should cause the list to grow automatically.
For example with a list of 3 items, I would like to insert element at index 6. Is this possible in python without first having to reinitialize the list?
It seems Python will merely append to the list if you try to insert an item at index 6 in my example.
You could write a function which, given a list, an index, and an element, inserts the element in the list before the index if the index is in range (in which case this is equivalent to the built-in insert method) or extends the list by enough Nones to fill it out before tacking it on the end:
>>> def put(xs,i,e):
n = len(xs)
if i <= n:
xs.insert(i,e)
else:
xs.extend([None]*(i-n-1))
xs.append(e)
>>> xs = [1,2,3]
>>> put(xs,6,10)
>>> xs
[1, 2, 3, None, None, 10]
>>>
Related
I need to create a python function that takes a list of numbers (and possibly lists) and returns a list of both the nested level and the sum of that level. For example:
given a list [1,4,[3,[100]],3,2,[1,[101,1000],5],1,[7,9]] I need to count the values of all the integers at level 0 and sum them together, then count the integers at level 1 and sum them together, and so on, until I have found the sum of the deepest nested level.
The return output for the example list mentioned above should be:
[[0,11], [1,25], [2,1201]]
where the first value in each of the lists is the level, and the second value is the sum. I am supposed to use recursion or a while loop, without importing any modules.
My original idea was to create a loop that goes through the lists and finds any integers (ignoring nested lists), calculate the sum, then remove those integers from the list, turn the next highest level into integers, and repeat. However, I could not find a way to convert a list inside of a list into indivual integer values (essentially removing the 0th level and turning the 1st level into the new 0th level).
The code that I am working with now is as follows:
def sl(lst,p=0):
temp = []
lvl = 0
while lst:
if type(lst[0]) == int:
temp.append(lst[0])
lst = lst[1:]
return [lvl,sum(temp)]
elif type(lst[0]) == list:
lvl += 1
return [lvl,sl(lst[1:],p=0)]
Basically, I created a while loop to iterate through, find any integers, and append it to a temp list where I could then find the sum. But, I cannot find a way to make the loop access the next level to do the same, especially when the original list is going up and down in levels from left to right.
I would do it like this:
array = [1, 4, [3, [100]], 3, 2, [1, [101, 1000], 5], 1, [7, 9]]
sum_by_level = []
while array:
numbers = (element for element in array if not isinstance(element, list))
sum_by_level.append(sum(numbers))
array = [element for list_element in array if isinstance(list_element, list) for element in list_element]
print(sum_by_level)
print(list(enumerate(sum_by_level)))
Gives the output:
[11, 25, 1201]
[(0, 11), (1, 25), (2, 1201)]
So I sum up the non-list-elements and then take the list-elements and strip of the outer lists. I repeat this until the array is empty which means all levels where stripped off. I discarded to directly saving the level-information as it is just the index, but if you need that you can use enumerate for that (gives tuples though instead of lists).
append will add an item to the end of the list.
l = [1,2,3,4]
l.append(5)
outputs
[1, 2, 3, 4, 5]
now instead of adding 5 at the end of the list I would like to add it to a random location in the list. let's say 5 is being added to index 2. Number 3 will move one index forward.
[1,2,5,3,4]
You could use insert method of list.
import random
l = [1,2,3,4]
l.insert(random.randint(0, len(l)), 5)
First argument of the method is index, the second argument is value. See documentation.
Use Insert where first argument is index (position), 2nd is value
l.insert(2, 5)
I am referring to this this specific answer Making nested lists same length. Since I don't have the permissions to comment yet and answering with a question to that topic would violate the rules, I am asking a new question.
I don't fully understand the answer.
In my understanding the iterator row in the for-loop is usually an integer value which iterates over each element in myList. So how is it possible to use len(row) as part of the condition since it is just an integer? Is there something I am missing?
I have tried to apply this solution to my code but as expected I receive an error saying
TypeError: object of type 'int' has no len()
args = ("object of type 'int' has no len()",)
with_traceback = <built-in method with_traceback of TypeError object>
referring to this line
row.extend(['null'*(len(maxSS7) - len(row))])
Further I don't understand the use of .extend with row which is the iterator and not a list.
Here is the relevant part from the answer.
maxLen = max(map(len, myList))
for row in myList:
if len(row) < maxLen:
row.extend(...)
A brief walkthrough would be greatly appreciated.
Or maybe there is a better way to adjust the lengths of all nested list to same length.
Ok, lets go through it line by line. Personally I don't think map is very idiomatic in Python so I would write this:
maxLen = max(map(len, myList))
As a generator expresion:
max_len = max(len(item) for item in my_list)
The second version is almost plain English: let max_len be the maximum value among the length of each item in my_list.
The best way to understand something in Python is just fire up the REPL and try it. So if you have my_list as a list of lists:
my_list = [[1], [1, 2], [1, 2, 3]]
The above will get you the length of the largest item: 3
Now you want to make every item the same size. How can you do that? One way is to append None items to it. For each item in the list, you test if the length of the item is smaller then the largest item in the list and it is almost plain English:
for item in list: # for each item in the list
while len(item) < max_len: # while the item length is smaller than 3
item.append(None) # append None to the item
You may want to do a bit of premature optimization and call extend once instead of calling append several times because you think performance will be better this way (but you can't really tell it unless you have profiled both solutions):
for item in list:
if len(item) < max_len:
item.extend([None] * (max_len - len(item)))
Now what is going on here? In Python, list + list concatenates two copies of list, and list * 3 is the same as list + list + list. So in the first iteration of the for loop, item is [1], len(item) is 1 and max_len - len(item) is 3 - 1. Finally, [None] * 2 is [None, None] so after the call to extend the first item will be [1, None, None]. Same thing for the second item, its length is 2, 3 minus 2 is one and it will end up as [1, 2, None]. The 3rd item has the same length as max_len (3) so the if condition is false. The result will be:
[[1, None, None], [1, 2, None], [1, 2, 3]]
All lists in the list of lists now have the same size, 3. For the sake of completion, for such a small list the extend version is less than 1 microsecond faster than the append one so barely worth the trouble (1.64 µs versus 1.7 µs in Python 3.6 running on my Mac).
for row in myList:
You created a variable called row which refers to an item within myList.
row is an integer.
You can get len of a list. Not an integer.
You messed up making your list. Troubleshoot it by printing the myList and seeing what the structure looks like so you know what you're iterating through cause it's probably not a 2d list.
>>> n = [1, 2, 3]
>>> for item in n:
... item *= 2
...
>>> print n
[1, 2, 3]
I expect the result of the above code to be [2, 4, 6], While obviously it's not.
Then I tried for i in range(n) as follows
>>> n = [1, 2, 3]
>>> for i in range(len(n)):
... n[i] *= 2
...
>>>
>>> n
[2, 4, 6]
This seems OK.
And my question is that, what's the essential difference between these two for loop method? What cause the unexpected result above?
If it helps, the first loop is equivalent to:
for i in range(len(n)):
item = n[i]
item *= 2
In other words, it first binds item to the i-th element of the list, and then rebinds it to a new object whose value is double that of the i-th element. It does not change any of the list's elements.
A good way to implement this loop is using a list comprehension:
n = [item * 2 for item in n]
You can't modify the object that represents the current iteration.
Well, actually, you can, but it won't change the object that is held in the list.
what's the essential difference between these two for loop method?
You iterate over objects in the list in the first example (and try to modify that said object directly - it doesn't change the list's element itself).
And you iterate over the list of integers in the second example (and actually modify the given list's element, so you modify the list content).
item is simply a local name. It is originally assigned by the for loop to point to the current element, but if you reassign it to point to something else, that has no effect on the original.
But if you use an index to reference an element in the original list, you can mutate that list to contain different values.
There's no assignment in for item in lst. You're operating on the object itself, which is immutable, so it just creates a new object for you when you do the *= call, assigns it to item, then throws it away on the next iteration of the loop.
When you do for i in range(len(lst)) you're assigning the new object to the ith element of lst.
Beginner here, learning python, was wondering something.
This gives me the second element:
list = [1,2,3,4]
list.index(2)
2
But when i tried this:
list = [0] * 5
list[2] = [1,2,3,4]
list.index[4]
I get an error. Is there some way to pull the index of an element from an array, no matter what list it's placed into? I know it's possible with dictionaries:
info = {first:1,second:2,third:3}
for i in info.values:
print i
1
2
3
Is there something like that for lists?
The index method does not do what you expect. To get an item at an index, you must use the [] syntax:
>>> my_list = ['foo', 'bar', 'baz']
>>> my_list[1] # indices are zero-based
'bar'
index is used to get an index from an item:
>>> my_list.index('baz')
2
If you're asking whether there's any way to get index to recurse into sub-lists, the answer is no, because it would have to return something that you could then pass into [], and [] never goes into sub-lists.
list is an inbuilt function don't use it as variable name it is against the protocol instead use lst.
To access a element from a list use [ ] with index number of that element
lst = [1,2,3,4]
lst[0]
1
one more example of same
lst = [1,2,3,4]
lst[3]
4
Use (:) semicolon to access elements in series first index number before semicolon is Included & Excluded after semicolon
lst[0:3]
[1, 2, 3]
If index number before semicolon is not specified then all the numbers is included till the start of the list with respect to index number after semicolon
lst[:2]
[1, 2]
If index number after semicolon is not specified then all the numbers is included till the end of the list with respect to index number before semicolon
lst[1:]
[2, 3, 4]
If we give one more semicolon the specifield number will be treated as steps
lst[0:4:2]
[1, 3]
This is used to find the specific index number of a element
lst.index(3)
2
This is one of my favourite the pop function it pulls out the element on the bases of index provided more over it also remove that element from the main list
lst.pop(1)
2
Now see the main list the element is removed..:)
lst
[1, 3, 4]
For extracting even numbers from a given list use this, here i am taking new example for better understanding
lst = [1,1,2,3,4,44,45,56]
import numpy as np
lst = np.array(lst)
lst = lst[lst%2==0]
list(lst)
[2, 4, 44, 56]
For extracting odd numbers from a given list use this (Note where i have assingn 1 rather than 0)
lst = [1,1,2,3,4,44,45,56]
import numpy as np
lst = np.array(lst)
lst = lst[lst%2==1]
list(lst)
[1, 1, 3, 45]
Happy Learning...:)
In your second example, your list is going to look like this:
[0, 0, [1, 2, 3, 4], 0, 0]
There's therefore no element 4 in the list.
This is because when you set list[2], you are changing the third element, not updating further elements in the list.
If you want to replace a range of values in the list, use slicing notation, for example list[2:] (for 'every element from the third to the last').
More generally, the .index method operates on identities. So the following will work, because you're asking python where the particular list object you inserted goes in the list:
lst = [0]*5
lst2 = [1,2,3,4]
lst[2] = lst2
lst.index(lst2) # 2
The answer to your question is no, but you have some other issues with your code.
First, do not use list as a variable name, because its also the name of the built-in function list.
Secondly, list.index[4] is different than list.index(4); both will give errors in your case, but they are two different operations.
If you want to pull the index of a particular element then index function will help. However, enumerate will do similar to the dictionary example,
>>> l=['first','second','third']
>>> for index,element in enumerate(l):
... print index,element
...
output
0 first
1 second
2 third