Python:How to get the same row a number of times [duplicate] - python

This question already has answers here:
Create list of single item repeated N times
(9 answers)
Closed 5 years ago.
I need to get same raw multiple times like bellow.
A=[2,3,4,5]
B=[[2,3,4,5],[2,3,4,5],[2,3,4,5],[2,3,4,5],...,[2,3,4,5]]
Number of rows can be change.
How can I do this problem?

Try this:
B = [[i for i in A] for n in range(5)]
Change the value in the range () call to change the number of copies. This doesn't suffer from reference sharing like the other answers.
online example
Or a shorter equivalent:
B = [A[:] for n in range(5)]
This also doesn't suffer from reference sharing because the slice operator creates a deep copy* as well.
online example
* at least in terms of this input

As has been pointed out, just doing list comprehension in the simplest way will only make multiple references to the same old list. To instead ensure we get a new copy of the list, we can do:
A = [2, 3, 4, 5]
B = [list(A) for i in range(10)]
where list(A) ensures that we get a copy of A instead of a reference to the same list.

You can also do:
B=([A.copy()]*10)
However, it can produce references between the lists in B if their elements are complex object. But if you're using it for ints, strings and others basic stuffs it's going to work well.

A = [1,2,3]
B= []
n= 5
for i in range(5):
B.append(A)
where A is list, B is resultant list and n is number of rows

Related

Remove duplicate of a list via list matching in Python [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Removing duplicates in lists
(56 answers)
Closed 7 days ago.
I have chosen a slightly different procedure to remove duplicates of a list. I want to keep a new list in parallel, in which each duplicate is added. Afterwards I check if the element is present in the "newly created list" in order to delete it.
The code looks like this:
# nums = [1,1,2] or [0,0,1,1,1,2,2,3,3,4]
t = []
nums_new = nums
for i in nums:
if nums[i] not in t:
t.append(nums[i])
else:
nums_new.remove(nums[i])
nums = nums_new
print(nums)
For the case when nums = [1,1,2] this works fine and returns [1,2].
However, for nums = [0,0,1,1,1,2,2,3,3,4] this case does not seem to work as I get the following output: [0, 1, 2, 2, 3, 3, 4].
Why is this? Can someone explain me the steps?
There are two issues with your code:
Since you are iterating over a list, for i in nums, i is your actual number, not the indexer, so you should just use i instead of nums[i].
nums_new = nums will not actually make a copy of nums, but instead it will make a second binding to the very same list. So you should write nums_new = nums.copy() to avoid changing your original list while you iterate over it.
With those two changes your code works as you wish:
nums = [0,0,1,1,1,2,2,3,3,4]
t = []
nums_new = nums.copy()
for i in nums:
if i not in t:
t.append(i)
else:
nums_new.remove(i)
nums = nums_new
print(nums)
Returns [0,1,2,3,4].
Of course this is an academic exercise of some kind, but note that the Pythonic way to remove duplicates from a list is:
list(dict.fromkeys(nums)) if you want to preserve the order, and
list(set(nums)) for a slightly faster method if you do not care about order.

Why doesn`t list[:][0] get me the first row of the list? [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
For the following:
list=[[2, 3, 5], [7, 8, 9]]
Why does [list[0][0], list[1][0]] represent the first row ([2, 7]), but the command list[:][0] or list[0:2][0] returns the first column ([2, 3, 5])?
The way I see it list[:][0] should get all the possible values for the first parameter (that is 0 and 1) and 0 for the second, meaning it would return the first row. Instead what it does is return the first column and I can't understand why.
In python, the [a:b:c] syntax creates a new list. That is,
list = [1,2,3]
print(list[:])
is going to print a list, not a value.
Therefore, when you say list[:][0] you are making a copy of the original list (list[:]) and then accessing item 0 within it.
Of course you know, item 0 of the original list (list[0]) is another list.
I think you want:
[sl[0] for sl in list]
Elaboration:
This is called a "comprehension." It is a compact special syntax for generating lists, dicts, and tuples by processing or filtering other iterables. Basically {..}, [..], and (..) with an expression inside involving a for and optionally an if. Naturally, you can have multiples (like [x for x in y for y in z]) of the for, and multiples of the if.
In your case, it's pretty obvious you want a list. So []. You want to make the list by taking the first item from each sublist. So [sl[0] for sl in list].
Here's a more-detailed article: http://carlgroner.me/Python/2011/11/09/An-Introduction-to-List-Comprehensions-in-Python.html

Retrieving list elements in Python [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
I'm a beginner attempting to learn Python. I am familiarising myself with the list data type; I've defined the following list:
>>> numbers = [1, 2, 3, 4]
Typing:
>>> numbers[0]
1
>>> numbers[1]
2
>>> numbers[2]
3
>>> numbers[3]
4
Given this, why do I get the following when I attempt to retrieve the following list elements:
>>> numbers[0:3]
[1, 2, 3]
Why isn't the list element '4' included in the response from the interpreter?
Thank you for your help.
Slice notation does not include the last element (similar to the range() function in that respect). If you want to include the last element, simply omit an index. Also, the default start is the beginning, so you don't need 0 there either:
>>> numbers[:]
[1, 2, 3, 4]
Note that this is a (shallow) copy of numbers. If you save a reference to it, you can mutate it without affecting the original numbers.
That's how slicing works in Python. To quote a tutorial:
Note how the start is always included, and the end always excluded.
This makes sure that s[:i] + s[i:] is always equal to s.
The example uses a string, but slicing works the same way with lists.
numbers[0:3] list from 0 up to 3 but 3 is excluded (like range(0,3))

Basic python: how to increase value of item in list [duplicate]

This question already has answers here:
Why does this iterative list-growing code give IndexError: list assignment index out of range? How can I repeatedly add (append) elements to a list?
(9 answers)
Closed 4 months ago.
This is such a simple issue that I don't know what I'm doing wrong. Basically I want to iterate through the items in an empty list and increase each one according to some criteria. This is an example of what I'm trying to do:
list1 = []
for i in range(5):
list1[i] = list1[i] + 2*i
This fails with an list index out of range error and I'm stuck. The expected result (what I'm aiming at) would be a list with values:
[0, 2, 4, 6, 8]
Just to be more clear: I'm not after producing that particular list. The question is about how can I modify items of an empty list in a recursive way. As gnibbler showed below, initializing the list was the answer. Cheers.
Ruby (for example) lets you assign items beyond the end of the list. Python doesn't - you would have to initialise list1 like this
list1 = [0] * 5
So when doing this you are actually using i so you can just do your math to i and just set it to do that. there is no need to try and do the math to what is going to be in the list when you already have i. So just do list comprehension:
list1 = [2*i for i in range(5)]
Since you say that it is more complex, just don't use list comprehension, edit your for loop as such:
for i in range(5):
x = 2*i
list1[i] = x
This way you can keep doing things until you finally have the outcome you want, store it in a variable, and set it accordingly! You could also do list1.append(x), which I actually prefer because it will work with any list even if it's not in order like a list made with range
Edit: Since you want to be able to manipulate the array like you do, I would suggest using numpy! There is this great thing called vectorize so you can actually apply a function to a 1D array:
import numpy as np
list1 = range(5)
def my_func(x):
y = x * 2
vfunc = np.vectorize(my_func)
vfunc(list1)
>>> array([0, 2, 4, 6, 8])
I would advise only using this for more complex functions, because you can use numpy broadcasting for easy things like multiplying by two.
Your list is empty, so when you try to read an element of the list (right hand side of this line)
list1[i] = list1[i] + 2*i
it doesn't exist, so you get the error message.
You may also wish to consider using numpy. The multiplication operation is overloaded to be performed on each element of the array. Depending on the size of your list and the operations you plan to perform on it, using numpy very well may be the most efficient approach.
Example:
>>> import numpy
>>> 2 * numpy.arange(5)
array([0, 2, 4, 6, 8])
I would instead write
for i in range(5):
list1.append(2*i)
Yet another way to do this is to use the append method on your list. The reason you're getting an out of range error is because you're saying:
list1 = []
list1.__getitem__(0)
and then manipulate this item, BUT that item does not exist since your made an empty list.
Proof of concept:
list1 = []
list1[1]
IndexError: list index out of range
We can, however, append new stuff to this list like so:
list1 = []
for i in range(5):
list1.append(i * 2)

Remove the last N elements of a list

Is there a a better way to remove the last N elements of a list.
for i in range(0,n):
lst.pop( )
Works for n >= 1
>>> L = [1,2,3, 4, 5]
>>> n=2
>>> del L[-n:]
>>> L
[1, 2, 3]
if you wish to remove the last n elements, in other words, keep first len - n elements:
lst = lst[:len(lst)-n]
Note: This is not an in memory operation. It would create a shallow copy.
As Vincenzooo correctly says, the pythonic lst[:-n] does not work when n==0.
The following works for all n>=0:
lst = lst[:-n or None]
I like this solution because it is kind of readable in English too: "return a slice omitting the last n elements or none (if none needs to be omitted)".
This solution works because of the following:
x or y evaluates to x when x is logically true (e.g., when it is not 0, "", False, None, ...) and to y otherwise. So -n or None is -n when n!=0 and None when n==0.
When slicing, None is equivalent to omitting the value, so lst[:None] is the same as lst[:] (see here).
As noted by #swK, this solution creates a new list (but immediately discards the old one unless it's referenced elsewhere) rather than editing the original one. This is often not a problem in terms of performance as creating a new list in one go is often faster than removing one element at the time (unless n<<len(lst)). It is also often not a problem in terms of space as usually the members of the list take more space than the list itself (unless it's a list of small objects like bytes or the list has many duplicated entries). Please also note that this solution is not exactly equivalent to the OP's: if the original list is referenced by other variables, this solution will not modify (shorten) the other copies unlike in the OP's code.
A possible solution (in the same style as my original one) that works for n>=0 but: a) does not create a copy of the list; and b) also affects other references to the same list, could be the following:
lst[-n:n and None] = []
This is definitely not readable and should not be used. Actually, even my original solution requires too much understanding of the language to be quickly read and univocally understood by everyone. I wouldn't use either in any real code and I think the best solution is that by #wonder.mice: a[len(a)-n:] = [].
Just try to del it like this.
del list[-n:]
I see this was asked a long ago, but none of the answers did it for me; what if we want to get a list without the last N elements, but keep the original one: you just do list[:-n]. If you need to handle cases where n may equal 0, you do list[:-n or None].
>>> a = [1,2,3,4,5,6,7]
>>> b = a[:-4]
>>> b
[1, 2, 3]
>>> a
[1, 1, 2, 3, 4, 5, 7]
As simple as that.
Should be using this:
a[len(a)-n:] = []
or this:
del a[len(a)-n:]
It's much faster, since it really removes items from existing array. The opposite (a = a[:len(a)-1]) creates new list object and less efficient.
>>> timeit.timeit("a = a[:len(a)-1]\na.append(1)", setup="a=range(100)", number=10000000)
6.833014965057373
>>> timeit.timeit("a[len(a)-1:] = []\na.append(1)", setup="a=range(100)", number=10000000)
2.0737061500549316
>>> timeit.timeit("a[-1:] = []\na.append(1)", setup="a=range(100)", number=10000000)
1.507638931274414
>>> timeit.timeit("del a[-1:]\na.append(1)", setup="a=range(100)", number=10000000)
1.2029790878295898
If 0 < n you can use a[-n:] = [] or del a[-n:] which is even faster.
This is one of the cases in which being pythonic doesn't work for me and can give hidden bugs or mess.
None of the solutions above works for the case n=0.
Using l[:len(l)-n] works in the general case:
l=range(4)
for n in [2,1,0]: #test values for numbers of points to cut
print n,l[:len(l)-n]
This is useful for example inside a function to trim edges of a vector, where you want to leave the possibility not to cut anything.

Categories

Resources