This question already has answers here:
Concatenating two range function results
(8 answers)
How can I generate a list of consecutive numbers? [duplicate]
(8 answers)
Closed 3 years ago.
in python is there a way to create of list that will skip numbers and will continue after skipping? something like the following code:
x = [1...3, 6...10]
print(x)
# [1,2,3,6,7,8,9,10]
Well its easy to write a for loop and then skip each defined index/value, or i can just use range, what I am looking for is a shorter more readable line. If not I can understand.
Simplest way to do this is to call range() and unpack result inside list assignment.
x = [*range(1, 4), *range(6, 11)]
Alternatively you can use itertools.chain:
>>> import itertools
>>> list(itertools.chain(range(1, 5), range(20, 25)))
[1, 2, 3, 4, 20, 21, 22, 23, 24]
If numpy is an option, you can use np.r_ to concatenate slice objects:
import numpy as np
np.r_[1:4, 6:11]
# array([ 1, 2, 3, 6, 7, 8, 9, 10])
You can turn it into a recursive function:
def recursive_ranges(ranges):
if len(ranges) == 1:
return list(range(*ranges[0]))
else:
return list(range(*ranges[0])) + recursive_ranges(ranges[1:])
You can then call this, specifying ranges as a list of lists:
ranges = [[1, 4], [6, 11]]
recursive_ranges(ranges)
# [1, 2, 3, 6, 7, 8, 9, 10]
Note the *ranges[0] is used to unpack the elements in ranges[0] into individual arguments. Essentially the recursive function keeps grabbing the first element of ranges, each element of which is a two-element array, and passing those numbers into the range() method as two different values instead of one array. That's what the * does, it unpacks the array. First call, you unpack [1, 4] into range(1, 4) and then append the next call of the recursive function to it.
Basically this unpacks into the following:
list(range(1, 4)) + list(range(6, 11))
but you get to use a much more compact syntax, just passing a list of lists.
Related
Hello I have a few lists and im trying to create a new list of the highest values repsectively. for an example, these are the lists:
list1 = 5, 1, 4, 3
list2 = 3, 4, 2, 1
list3 = 10, 2, 5, 4
this is what I would like it to return:
[10, 4, 5, 4]
I thought that I could do a something like this:
largest = list(map(max(list1, list2, list3)))
but I get an error that map requires more than 1 argument.
I also thought I could write if, elif statements for greater than but it seems like it only does the first values and returns that list as the "greater value"
thanks for any help
This is the "zip splat" trick:
>>> lists = [list1, list2, list3]
>>> [max(col) for col in zip(*lists)]
[10, 4, 5, 4]
You could also use numpy arrays:
>>> import numpy as np
>>> np.array(lists).max(axis=0)
array([10, 4, 5, 4])
You have used map incorrectly. Replace that last line with this:
largest = list(map(max, zip(list1, list2, list3)))
In map, the first argument is the function to be applied, and the second argument is an iterable which will yield elements to apply the function on. The zip function lets you iterate over multiple iterables at once, returning tuples of corresponding elements. So that's how this code works!
Using map's iterableS argument has an implicit zip-like effects on the iterables.
map(max, *(list1, list2, list3))
This question already has answers here:
Finding and replacing elements in a list
(10 answers)
Closed 2 years ago.
Is there a fancy method for replacing a specific value of a list with another value?
Like a shortcut for this:
>>> l = list(range(10))
>>> replacing = 3
>>> l[l.index(replacing)] = 4
>>> l
[0, 1, 2, 4, 4, 5, 6, 7, 8, 9]
With the example I gave it's easy enough to do via the [l.index()], but when the list reference is a few dots away it starts getting ugly.
It would be so much prettier to do something like this:
>>> some.thing.very.far.away.list = list(range(10))
>>> some.thing.very.far.away.list.replace(3, 4)
Edit:
I forgot to say why.
I want to edit the same list, and only edit one of the values.
I'm actually kind of supprized that lists doesn't have a built-in method like list.replace(old, new[, max), considering that strings do and it seems like python has built-ins for just about everying.
Build a new list with a list comprehension:
new_items = [4 if x==3 else x for x in l]
You can modify the original list in-place if you want, but it doesn't actually save time:
items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for index, item in enumerate(items):
if (item ==3 2):
items[index] = 4
you can assign "some.thing.very.far.away.list" to a temporary variable and apply replace function
some.thing.very.far.away.list = temp
something.very.far.away.list = temp.replace(x,y)
This can be a trick:
First define a dictionary with values you want to replace, than use a list comprehension using dictionary get with a default value.
You are passing el both as a key of the dictionary and as default value. If the key is found the corresponding value will be replaced otherwise the default value itself.
>>> l = [0, 1, 2, 4, 4, 5, 6, 7, 8, 9]
>>> rpl = {1: 23, 6: 12}
>>> [rpl.get(el, el) for el in l]
[0, 23, 2, 4, 4, 5, 12, 7, 8, 9]
You can use map method to iterate and replace certain value.
syntax : map(function, iterable, ...)
The returned value from map() (map object) can then be passed to functions like list() (to create a list), set() (to create a set) and so on.
l = list(range(10))
replacing = 3
l = list(map(lambda x: 4 if x == replacing else x, l)) # iterating over list l and replacing certain value using map method and converting map object in to another list.
print(l)
output = [0, 1, 2, 4, 4, 5, 6, 7, 8, 9]
it takes two parameter function and iterable. map() passes each item of the iterable to this function.
where lambda function takes argument x from sequence (l), assign 4 if x is equal to 4 .
to know more about map method Python map()
This question already has answers here:
Zip lists in Python
(10 answers)
Closed 2 years ago.
My input is
tbl_ports = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
And my expected output is
[[1,5,9], [2,6,10], [3,7,11], [4,8,12]]
My limit was to do the following to create the output reorder_list
reorder_list = []
for i in range(len(tbl_ports)):
for col in tbl_ports:
reorder_list.append(col[i])
reorder_list=[1, 5, 9, 2, 6, 10, 3, 7, 11]
How can I contain them in a list of 3 elements?
To fix the code that you already have, you need to create a new list every time a row is complete, such as:
reorder_list = []
for i in range(len(tbl_ports)):
reorder_list.append([])
for col in tbl_ports:
reorder_list[-1].append(col[i])
Which would yield the following result:
[[1, 5, 9], [2, 6, 10], [3, 7, 11]]
You can also use a more pythonic method of solving the problem,
list(zip(*tbl_port))
Which would yield a list of tuples:
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
If you want a list of lists, then you can simply just use list comprehension:
[list(e) for e in zip(*tbl_port)]
Edit:
for an explanation of why zip(*list) works, you need to know what zip does.
zip is a function in python that takes in multiple lists, and outputs a generator of lists for each element in every corresponding list. So zip([1, 2, 3], [4, 5, 6]) would yield [(1, 4), (2, 5), (3, 6)].
the * basically expands the input into multiple positional arguments, where function(*[1, 2, 3, 4]) is equivalent to function(1, 2, 3, 4)
So the code passed in the input array as a list of arguments to the zip function, which then outputs the result in the order that you want.
The only remaining problem is that zip generates a generator instead of an actual list.
To solve that problem, simply call the list function on a generator to convert it into a list, or pass it in a list comprehension to yield the desired result.
This is exactly what the zip() function is for.
list(zip([1,2,3,4],'abcd'))
You can use the unpack syntax " * " to make python unpack your lists to the zip function.
tbl_ports = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
reorder_list = list(zip(*tbl_ports))
I have a file which contains a number of lists. I want to access the index of the values retrieved from each of these lists. I use the random function as shown below. It retrieves the values perfectly well, but I need to get the index of the values obtained.
for i in range(M):
print(krr[i])
print(krr[i].index(random.sample(krr[i],2)))
nrr[i]=random.sample(krr[i],2)
outf13.write(str(nrr[i]))
outf13.write("\n")
I got ValueError saying the two values retrieved are not in the list even though they exist...
To retrieve the index of the randomly selected value in your list you could use enumerate that will return the index and the value of an iterable as a tuple:
import random
l = range(10) # example list
random.shuffle(l) # we shuffle the list
print(l) # outputs [4, 1, 5, 0, 6, 7, 9, 2, 8, 3]
index_value = random.sample(list(enumerate(l)), 2)
print(index_value) # outputs [(4, 6), (6, 9)]
Here the 4th value 6 and 6th value 9 were selected - of course each run will return something different.
Also in your code you are printing a first sample of the krr[i] and then sampling it again on the next line assigning it to nrr[i]. Those two calls will result in different samples and might cause your IndexError.
EDIT after OP's comment
The most explicit way to then separate the values from the indexes is:
indexes = []
values = []
for idx, val in index_value:
indexes.append(idx)
values.append(val)
print indexes # [4, 6]
print values # [6, 9]
Note that indexes and values are in the same order as index_value.
If you need to reproduce the results, you can seed the random generator, for instance with random.seed(123). This way, every time you run the code you get the same random result.
In this case, the accepted solution offered by bvidal it would look like this:
import random
l = list(range(10)) # example list (please notice the explicit call to 'list')
random.seed(123)
random.shuffle(l) # shuffle the list
print(l) # outputs [8, 7, 5, 9, 2, 3, 6, 1, 4, 0]
index_value = random.sample(list(enumerate(l)), 2)
print(index_value) # outputs [(8, 4), (9, 0)]
Another approach is to use the random sample function random.sample from the standard library to randomly get an array of indices and use those indices to randomly choose elements from the list. The simplest way to access the elements is converting the list to a numpy array:
import numpy as np
import random
l = [1, -5, 4, 2, 7, 4, 8, 0, 9, 3]
print(l) # prints the list
random.seed(1234) # seed the random generator for reproducing the results
random_indices = random.sample(range(len(l)), 2) # get 2 random indices
print(random_indices) # prints the indices
a = np.asarray(l) # convert to array
print(list(a[random_indices])) # prints the elements
The output of the code is:
[1, -5, 4, 2, 7, 4, 8, 0, 9, 3]
[7, 1]
[0, -5]
You could try using enumerate() on your list objects.
According to the Python official documentation
enumerate() : Return an enumerate object. sequence must be a sequence, an iterator,
or some other object which supports iteration. The next() method of
the iterator returned by enumerate() returns a tuple containing a
count (from start which defaults to 0) and the values obtained from
iterating over sequence
A simple example is this :
my_list=['a','b','c']
for index, element in enumerate(my_list):
print(index, element)
# 0 a
# 1 b
# 2 c
Don't know if I understood the question though.
You are getting the random sample twice, which results in two different random samples.
This question already has answers here:
Expanding tuples into arguments
(5 answers)
Closed 4 years ago.
This is ugly. What's a more Pythonic way to do it?
import datetime
t= (2010, 10, 2, 11, 4, 0, 2, 41, 0)
dt = datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5], t[6])
Generally, you can use the func(*tuple) syntax. You can even pass a part of the tuple, which seems like what you're trying to do here:
t = (2010, 10, 2, 11, 4, 0, 2, 41, 0)
dt = datetime.datetime(*t[0:7])
This is called unpacking a tuple, and can be used for other iterables (such as lists) too. Here's another example (from the Python tutorial):
>>> range(3, 6) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5]
Refer https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists
dt = datetime.datetime(*t[:7])