Is there a way to write the following expression in way
that I will not repeat the variables twice? it's very annoying
when you have to write it multiple times.
['hello {} {}'.format(A,B) for A,B in product(As,Bs)]
That's exactly what you would do for a for loop anyway isn't it? Anyway, you can use map:
map(lambda x:'hello {} {}'.format(*x), product(As,Bs)]
I realize now the parameter expansion *x syntax might shorten what you wrote above as well (one variable only). If you intend to apply someFormatString.format(*x) always you can shorten this using a function to generate your formatter:
def mkStr(formatStr):
return lambda x,f=formatStr: f.format(*x)
Then you can map with
map(mkStr('hello {} {}'), product(As,Bs)]
and switch it up with different format strings.
with only a minor change you could get there:
['hello {} {}'.format(*ab) for ab in product(As, Bs)]
using *args-magic.
Related
So I'm trying to use the map function with a lambda to write each item of a list to a txt file on a new line
map(lambda x: text_file.write(f"{x}\n"), itemlist_with_counts_formatted)
I understand that map returns a map object, but I don't need the return value.
What I want is for the map function to compute the lambda, which adds "\n" to the end of each item in the given list.
I thought that map should do this (compute the function (lambda appends "\n") using arguments from the iterable) but nothing gets output to the txt file.
For clarity, I can totally do this with a list comprehension but I wanted to learn how to use map (and properly anonymous lambdas), so am looking for help solving it using these two functions specifically (if possible).
map(lambda x: text_file.write(f"{x}\n"), itemlist_with_counts_formatted)
I have also tried it without the f string, using just x + "\n" but this doesn't work either
Yes the txt file is open, and yes I can get it to work using other methods, the problem is exclusive to how I'm using map or how I'm using lambda, which must be wrong in some way. I've been doing this for 6 weeks so its probably something stupid but I've tried to figure it out myself and i just can't and I've checked but can't find anything on here - appreciate any help I can get.
You should really not use map for this task.
It looks fancy, but this is the same as using list comprehensions for side effects. It's considered bad practice.
[print(i) for i in range(3)]
Which should be replaced with:
for i in range(3):
print(i)
In you case, use:
for item in itemlist_with_counts_formatted:
text_file.write(f"item\n")
why your code did not work:
map returns a generator, nothing is evaluated until something consumes the generator. You would need to do:
list(map(lambda x: text_file.write(f"{x}\n"), itemlist_with_counts_formatted))
But, again, don't, this is useless, less efficient and less explicit.
But I really want a one-liner!
Then use:
text_file.write('\n'.join(itemlist_with_counts_formatted))
NB. unlike the other alternatives in this answer, this one does not add a trailing '\n' in the end of the file.
I really, really, want to use map:
text_file.writelines(map(lambda x: f'{x}\n', itemlist_with_counts_formatted))
i think that the problem is that this use of the map function is a bit unproper. As said in the documentation the map function returns a generator for the results iterable, while the write function is not returning anything. This might brake something during the map internals.
I'd suggest you to use map only to add line end and then use the writeline function on the resulting generator, something like:
text_file.writelines(map(lambda x: f"{x}\n", itemlist_with_counts_formatted))
(Not tested)
I have a set with multiple tuples: set1 = {(1,1),(2,1)} for example.
Now I want to pass each tuple of the set to a method with this signature: process_tuple(self, tuple).
I am doing it with a for loop like this:
for tuple in set1:
process_tuple(tuple)
Is there a better way to do it?
Your question is basically "how can I loop without using a loop". While it's possible to do what you're asking with out an explicit for loop, the loop is by far the clearest and best way to go.
There are some alternatives, but mostly they're just changing how the loop looks, not preventing it in the first place. If you want to collect the return values from the calls to your function in a list, you can use a list comprehension to build the list at the same time as you loop:
results = [process_tuple(tuple) for tuple in set1]
You can also do set or dict comprehensions if those seem useful to your specific needs. For example, you could build a dictionary mapping from the tuples in your set to their processed results with:
results_dict = {tuple: process_tuple(tuple) for tuple in set1}
If you don't want to write out for tuple in set1 at all, you could use the builtin map function to do the looping and passing of values for you. It returns an iterator, which you'll need to fully consume to run the function over the full input. Passing the map object to list sometimes makes sense, for instance, to convert inputs into numbers:
user_numbers = list(map(int, input("Enter space-separated integers: ").split()))
But I'd also strongly encourage you to think of your current code as perhaps the best solution. Just because you can change it to something else, doesn't mean you should.
I'm not sure how to go about this in Python. In searching for this, I have come across itertools but I'm not sure how I might apply it in this case.
What I am trying to do is create a script that can take a string input containing query marks (like AB?D?) and a set of options (ABC, DEF) to output all of the possible combinations, like below.
ABADD, ABADE, ABADF
ABBDD, ABBDE, ABBDF
ABCDD, ABCDE, ABCDF
In searching, I also found this but I'm not entirely sure how I might be able to implement this around my input.
Would it be most efficient to break down the input string into multiple substrings around the question marks (so the above example becomes AB + ? + D + ?). Would something like list (s) be suitable for this?
Thanks in advance for any help offered.
You can use itertools.product to get the combinations and string.format to merge those into the template string. (First, replace the ? with {} to get format string syntax.)
def combine(template, options):
template = template.replace('?', '{}')
for opts in itertools.product(*options):
yield template.format(*opts)
Example:
>>> list(combine('AB?D?', ['ABC', 'DEF']))
['ABADD', 'ABADE', 'ABADF', 'ABBDD', 'ABBDE', 'ABBDF', 'ABCDD', 'ABCDE', 'ABCDF']
At the moment, I have a piece of code with lots of lists equal to the function of another list, embedded in a loop in Python:
Power = [x,y,z]
Force = []
for i in range(len(Power)):
Force.append(((function(Power[i])-0.5))/slope)
I would like to simplify it down to:
Force = function(Power[i])-0.5))/slope)
but it doesn't work. It does however work when there's no function, just a simple relationship. Is this possible in Python?
You can use a list comprehension:
Force = [(function(x)-0.5)/slope for x in Power]
As far as I am aware the most concise / simplest way to do this is via list comprehension, in particular you can do something as follows:
Force = [(function(Power[i])-0.5)/slope for i in range(len(Power))]
Very similar to what you have already done earlier, but comes in a nice and simple one line expression.
I wan to turn this two lines of code into one.
for n in exceptions:
my_dict[n] += 1
It's bothering me that a small statement to increment a dictionary takes two lines. I'm sure this problem has bothered someone too.
for n in exceptions: my_dict[n] += 1
...but there is nothing wrong in the fact that the statement takes two lines. There are some python coding guidelines (PEP8) and they strongly encourage core readability. By putting those statements into a single line you lower the readability.
From PEP8:
While sometimes it's okay to put an if/for/while with a small body on
the same line, never do this for multi-clause statements. Also avoid
folding such long lines!
my_dict.update({n: my_dict[n] + 1 for n in exceptions})
This essentially uses dict.update to update the dictionary with values from another dictionary. And that other dictionary is built using a dictionary comprehension. Unfortunately, to get the my_dict[n] += 1 effect, we have to read the value explicitely again in the expression.
But I would argue a lot if it would be better than using a simple and clear for-loop for this.
On the other hand, as you seem to be just counting exceptions, you might want to consider using a Counter for your dictionary. It’s essentially an improved dictionary (meaning that you can use it just like a normal dictionary) but it comes with a few features that makes it perfect when counting things. For example, you could simplify above statement to just this:
my_dict.update({n: 1 for n in exceptions})
Or as you are just adding 1 for each, you can just pass the iterable exceptions directly:
my_dict.update(exceptions)
This would also have the benefit that exceptions which do not exist in my_dict yet, are automatically initialized. To create a Counter from your existing dictionary, you can just pass the original dictionary to the Counter constructor:
from collections import Counter
my_dict = Counter(my_dict)
Use a collections.Counter:
import collections
my_dict = collections.Counter(exceptions)
or, if my_dict is already defined to be a dict,
my_dict = collections.Counter(my_dict)
my_dict.update(exceptions)