I'm trying to make a bunch of tuples show only one decimal using a for loop.
Van = (500.3736434, 43.834434)
Vbn = (300.2321313, 64)
Vcn = (250.43513241, 12)
listap = [Van, Vbn, Vcn]
for i in range(0,len(listap)):
listap[i] = tuple([float("{0:.1f}".format(n)) for n in listap[i]])
The desired result is only displayed when I print a specific index in the list, like print(listap[0])for example. Anyway I can get the reduced tuples without using the list? for example, doing
print(Van)
>>> (500.4, 43.8)
Python tuples are immutable - you cannot modify them in place. What you could do is, instead to convert into the desired format and rename the converted variables to the same name -
Van, Vbn, Vcn = [tuple([float("{0:.1f}".format(n)) for n in el]) for el in listap]
print(Van)
# (500.4, 43.8)
You have to create a new tuple.
new_list = []
for old_tuple in listap:
new_tuple = tuple([round(i, 1) for i in old_tuple])
new_list.append(new_tuple)
print(new_list)
# [(500.4, 43.8), (300.2, 64), (250.4, 12)]
But, if you just want to print them as a list, you can do:
for old_tuple in listap:
print([round(i, 1) for i in old_tuple])
which outputs
[500.4, 43.8]
[300.2, 64]
[250.4, 12]
Related
My objective is to extract the dimensions of a pytorch Tensor, whose indices are not in a given list. I want to use broadcasting to do that like follows:
Sim = torch.rand((5, 5))
samples_idx = [0] # the index of dim that I don't want to extract
a = torch.arange(Sim.size(0)) not in samples_idx
result = Sim[a]
I assume a would be a Tensor with True/Flase with the dimension of 5.But I get the error RuntimeError: Boolean value of Tensor with more than one value is ambiguous. Anyone can help me to point out where it goes wrong? Thanks.
There is a misunderstanding between the concept of "dimension" and "indices". What you want is to filter Sim and keep only rows (the 0th dimension) which indices match a given rule.
Here is how you could do that:
Sim = torch.rand((5, 5))
samples_idx = [0] # the index of dim that I don't want to extract
a = [v for v in range(Sim.size(0)) if v not in samples_idx]
result = Sim[a]
a is not a boolean Tensor but a list of indices to keep. You then use it to index Sim on the 0th dimension (the rows).
not in is not an operation that can be broadcasted, you should use a regular Python comprehension list for it.
You could create a set containing the desired indices by substracting samples_idx from a set containing all indices:
>>> Sim = torch.rand(5, 5)
tensor([[0.9069, 0.3323, 0.8358, 0.3738, 0.3516],
[0.1894, 0.5747, 0.0763, 0.8526, 0.2351],
[0.0304, 0.7631, 0.3799, 0.9968, 0.6143],
[0.0647, 0.2307, 0.4061, 0.9648, 0.0212],
[0.8479, 0.6400, 0.0195, 0.2901, 0.4026]])
>>> samples_idx = [0]
The following essentially acts as your torch.arange not in sample_idx:
>>> idx = set(range(len(Sim))) - set(samples_idx)
{1, 2, 3, 4}
Then perform the indexing with idx:
>>> Sim[tuple(idx),:]
tensor([[0.1894, 0.5747, 0.0763, 0.8526, 0.2351],
[0.0304, 0.7631, 0.3799, 0.9968, 0.6143],
[0.0647, 0.2307, 0.4061, 0.9648, 0.0212],
[0.8479, 0.6400, 0.0195, 0.2901, 0.4026]])
Maybe this is a bit out of focus, but you could also try using boolean indexing.
>>> Sim = torch.rand((5, 5))
tensor([[0.8128, 0.2024, 0.3673, 0.2038, 0.3549],
[0.4652, 0.4304, 0.4987, 0.2378, 0.2803],
[0.2227, 0.1466, 0.6736, 0.0929, 0.3635],
[0.2218, 0.9078, 0.2633, 0.3935, 0.2199],
[0.7007, 0.9650, 0.4192, 0.4781, 0.9864]])
>>> samples_idx = [0]
>>> a = torch.ones(Sim.size(0))
>>> a[samples_idx] = 0
>>> result = Sim[a.bool(), :]
tensor([[0.4652, 0.4304, 0.4987, 0.2378, 0.2803],
[0.2227, 0.1466, 0.6736, 0.0929, 0.3635],
[0.2218, 0.9078, 0.2633, 0.3935, 0.2199],
[0.7007, 0.9650, 0.4192, 0.4781, 0.9864]])
This way you don't have to iterate all the samples_idx list checking the inclusion.
I'm having some issues trying to figure this out (as i'm a pure beginner to python).
I have a list of names:
names_2 = ["Lars", "Per", "Henrik"]
Which I need to convert into a tuple who hold each elements length + the element it self.
I tried this:
namesTuple = tuple(names_2 + [len(name) for name in names_2])
Output of this is: ('Lars', 'Per', 'Henrik', 4, 3, 6)
The output im looking for is ('Lars', 4, 'Per', 3, 'Henrik', 6)
Anyone who can help?
You can use a nested generator expression in the tuple constructor, for instance:
names_tuple = tuple(x for name in names_2 for x in (name, len(name)))
# ('Lars', 4, 'Per', 3, 'Henrik', 6)
If you were to build it in a looping approach, it makes sense to build a list first (tuples are immutable):
names = []
for name in names_2:
# extend (both at once)
names.extend((name, len(name)))
# OR append one by one (no spurious intermediate tuple)
# names.append(name)
# names.append(len(name))
names_tuple = tuple(names)
names_2 = ["Lars", "Per", "Henrik"]
names = []
for name in names_2:
names.append(name)
names.append(len(name))
names = tuple(names)
Iterate over the names, append the name itself and its length to a list, and convert the list to tuple.
Or as a one-liner (but you'll end up with a tuple of tuples):
names_2 = ["Lars", "Per", "Henrik"]
names = tuple((name, len(name)) for name in names_2)
Zip the list of names with the list of lengths, then flatten the resulting list and convert that to a tuple.
from itertools import chain
namesTuple = tuple(chain.from_iterable(zip(names_2, map(len, names_2))))
If you prefer something a little less "functional", you can use a generator expression.
namesTuple = tuple(chain.from_iterable((x, len(x)) for x in names_2))
or (repeating #schwobaseggl's answer)
namesTuple = tuple(value for name in names_2 for value in (name, len(name)))
First create a tuple of tuples : ((name_1,lenght_1), (name_2,lenght_2),...)
The zip function is existing for that.
Secondly, you have to flatten this tuple of tuples.
[In]
names = ["Lars", "Per", "Henrik"]
[In]
zip_tupled = tuple(zip(names, [len(x) for x in names]))
[Out]
zip_tupled = (('Lars', 4), ('Per', 3), ('Henrik', 6))
[In]
final = tuple(item for subtuple in zip_tupled for item in subtuple)
[Out]
final = ('Lars', 4, 'Per', 3, 'Henrik', 6)
This solution is quite close to the solution of schwobaseggl...But less direct/straight.
Stackoverflow : how to flatten a list
I have the following list:
list_c = ['42.2529, -73.7910', '42.079846, -76.499364', '42.361824, -73.597979', '42.035959, -73.580146']
I'd like to convert to this:
list_c2 = [(42.2529, -73.7910),(42.079846, -76.499364),(42.361824, -73.597979),(42.035959, -73.580146)]
The code am trying is:
list_c2 = [(list_c[i]) for i in range(0, len(list_c))]
print("list_c2 =", list_c)
Unfortunately, the result is exactly the same as list_c
I'm sorry, I misread you list initially. To convert this into pairs of floats, you'll need to split each string on its comma and then make each element a float, then pack them in a tuple:
list_c2 = [tuple(float(item) for item in s.split(',')) for s in list_c]
# [(42.2529, -73.791), (42.079846, -76.499364), (42.361824, -73.597979), (42.035959, -73.580146)]
The output I want to have is like:
the result is 8
the result is 16
the result is 24
the result is 32
the result is 40
So I do:
final = ''
for each_one in [1, 2, 3, 4, 5]:
result = 'the result is ' + str(each_one * 8)
final.join(result)
final.join('\n')
print final
But it doesn't work out. How can I adjust it?
final = ''
for each_one in [1, 2, 3, 4, 5]:
final += ('the result is ' + str( each_one * 8 )+'\n\n')
print final
I believe you are mixing join function with concatenation.
Not saying it would be impossible to do it with join,but
your code resembles usage of string concatenation.
Learn more about join here
You are misusing str.join; it actually works like
"x".join(["A", "B", "C"]) # => "AxBxC"
.join expects an iterable (ie a list or generator) of strings. If you pass it a single string, it will treat it as a list of characters:
"x".join("ABC") # => "AxBxC"
What you actually need to do is
lines = []
for num in [1, 2, 3, 4, 5]:
line = 'the result is ' + str(num * 8)
lines.append(line)
print('\n\n'.join(lines))
which gives
the result is 8
the result is 16
the result is 24
the result is 32
the result is 40
You can do the following:
print '\n\n'.join(['the result is {}'.format(each_one * 8) for each_one in range(1, 6)])
final = '\n'.join(["The result is " + str(num * 8) for num in [1,2,3,4,5]])
print(final) #or "print final" if Python 2
EDIT: if you want a line break in between each line, replace the '\n' with '\n\n'
EDIT#2:
The join method takes an iterable as its argument, which a list comprehension to a list counts. Any string calling the join method will concatenate the string in between the elements of the iterable in the join method argument. So a '\n' will appear concatenated to each element in the list I made via a list comprehension.
List comprehensions are key components of the language. They allow to dynamically create lists and can be useful for creating lists on-the-fly.
What it is saying, for each number in the list [1,2,3,4,5], do "The result is " + str(num * 8) on it, then take all the results and make a list out of it.
List comprehensions are great if you intend for a list object to be created. For example, you can use them to filter out a current list:
stringList = ["yes","no","yesterday"]
filtered = [item for item in stringList if "yes" in item]
#result is: ["yes", "yesterday"]
They are commonly misused as performing an operation over elements of an iterable, with no desire to have a list object. In that specific case, a simple for loop would be better.
There's another way to write this to be a bit easier and cleaner, if you'd like.
You can simply do:
for number in range(1,6):
print("The result is "+str(number*8))
Which outputs:
The result is 8
The result is 16
The result is 24
The result is 32
The result is 40
I'm reading through some log files and have a list of urls like this:
url looks like this with new line after every url
http://domain1.com
http://domain2.com
http://domain3.com
http://domain4.com
I now want to make a tuple and add a single value to each url. All values are the same.
It should look like this.
('http://domain1.com', 3)
('http://domain2.com', 3)
('http://domain3.com', 3)
('http://domain4.com', 3)
And finally, for further processing I need a list of tuples that should look like this:
[('http://domain1.com', 3), ('http://domain2.com', 3), ('http://domain3.com',3)...]
This is what i tried by myself:
#split urls with comma
separated_urls = url.split(', ')
num__of_lines = sum(1 for line in separated_urls)
#make a list of 3s for the length of the url list
list_of_threes = [3] * num__of_lines
combined_list = zip(separated_urls, list_of_threes)
final_list = tuple(combined_list)
print final_list
this gives me following output:
(('http://domain1.com', 3),)
(('http://domain2.com', 3),)
(('http://domain3.com', 3),)
(('http://domain4.com', 3),)
Can someone provide me a little help, to get the desired output?
Thanks
Use a list comprehension
#split urls with comma
separated_urls = url.split('\n')
final_list = [(url,3) for url in separated_urls]
EDIT: use split('\n') or (split() as newline is default) to split the url list up rather than split(', ')
You can do it two ways easily.
1) Old school for loop way:
output_list = []
for url in url.split():
output_list.append((url, 3))
2) Or the list comprehension way, as #Trengot mentioned:
output_list = [(url, 3) for url in url.split()]
The old school way is better suited if you wish to do any changes to the list and check some more before creating the output_list. For simple cases(even with a condition check), list comprehensions are the way to go :-)
EDIT: Reading through your comments, I guess you need to split them through "\n" character rather than comma separated. Updated the code accordingly, as split by default split the characters with "\n".
Good that you have found the answer.
Your code is accurate till the following lines
url = "http://domain1.com, http://domain2.com, http://domain3.com, http://domain4.com"
separated_urls = url.split(', ')
list_of_threes = [3] * len(separated_urls)
combined_list = zip(separated_urls, list_of_threes)
The problem is your casting. Just cast the combined_list to a list
print (list(combined_list))
and bingo, you get your output
[('http://domain1.com', 3), ('http://domain2.com', 3), ('http://domain3.com', 3), ('http://domain4.com', 3)]
in code statement final_list = tuple(combined_list) is converting list into tuple.
So if you want output as list and items of list as tuple then you can remove above statement.
check by print combined_list statement in your code.
Use List Comprehensions
>>> urls = """
... http://domain1.com
... http://domain2.com
... http://domain3.com
... http://domain4.com"""
>>> print [(i, 3) for i in urls.split('\n') if i.strip()]
[('http://domain1.com', 3), ('http://domain2.com', 3), ('http://domain3.com', 3), ('http://domain4.com', 3)]