-5

I have the following list and variable i:

probs = [1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9]
i = 3

I want to change the values inside the list for the index given in variable i to 3/9, and the rest of the values to 8/9. So the desired result with the above conditions would be:

probs = [8/9, 8/9, 8/9, 3/9, 8/9, 8/9, 8/9, 8/9, 8/9]

I prefer to do this with list comprehension for efficiency, any ideas?

apol96
  • 200
  • 12
  • the values inside list are strings right ? And you to convert the values to 3/9 and 8/9 or you want to multiple by 3 and 8 – EXODIA Mar 12 '21 at 18:04
  • 1
    The values are floats and I want to convert the values, not multiply. – apol96 Mar 12 '21 at 18:06
  • 3
    *"I prefer to do this with list comprehension for efficiency"* - Um, what? List comprehension is [much less efficient](https://tio.run/##nZDNasMwEITveoohECQVU9P6Eqf4SYIoLpXbhegHaQPp07uSDDH02L2smJn9tGz84e/gh1NM67qk4MDkLDHIxZAYyUY7sxDZ8i1igpRSxBQ@cnlfDi/9eOjwv2YEFcYgKlFkntk667lxBUrJxzdDP4IW0Ocd0wSCvWaLUxGXkJpKHmn2X1ZdrVdtTGsjuz@YMmHwhD3zhtYvZOoi/VgmjBAV@r4jB31unCpndlydfdvNq8WF4cir7WCqRju0q2n9CMVEnpU8Pr8uEkfURMlt/ubpdf0F) than list repetition for this (comparing with the list comprehension from the answer that you accepted). – Manuel Mar 13 '21 at 03:08
  • 3
    Using a list comprehension is about 5 times slower than something like `lst = [8/9] * 9 ; lst[i] = 1/9` - and it gets much, much worse with longer lists. – Thierry Lathuille Mar 13 '21 at 08:30

4 Answers4

5

you can do this using an expression inside a list comprehension.

probs = [3 / 9 if i == index else 8 / 9 for index, _ in enumerate(probs)]
Vishal Singh
  • 6,014
  • 2
  • 17
  • 33
5

Here's a list comprehension that does what you asked for:

probs = ["1/9", "1/9", "1/9", "1/9", "1/9", "1/9", "1/9", "1/9", "1/9"]
i = 3

probs = ["3/9" if idx == i else "8/9" for idx in range(len(probs))]
print(probs)
# Prints ['8/9', '8/9', '8/9', '3/9', '8/9', '8/9', '8/9', '8/9', '8/9']

Note that I converted the fractions to strings, otherwise they'd be printed as floats. If you want them to be floats, you can do this:

probs = [1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9]
i = 3

probs = [3/9 if idx == i else 8/9 for idx in range(len(probs))]
print(probs)
# Prints [0.8888888888888888, 0.8888888888888888, 0.8888888888888888, 0.3333333333333333, 0.8888888888888888, 0.8888888888888888, 0.8888888888888888, 0.8888888888888888, 0.8888888888888888]

Also, note that this list comprehension is actually no faster than a normal for-loop.

M-Chen-3
  • 2,036
  • 5
  • 13
  • 34
  • *"list comprehensions are actually no faster than a normal for-loop"* - How would you write an equally fast normal for-loop here? – Manuel Mar 13 '21 at 03:12
  • 1
    @Manuel `for idx in range(len(probs)): probs[idx] = 3/9 if idx == i else 8/9` – M-Chen-3 Mar 13 '21 at 16:15
  • 1
    Ok, yes, I had actually tested that one and it was even a bit *faster* than your list comp (both *much* slower than the list repetition solution I [showed earlier](https://stackoverflow.com/questions/66604932/list-comprehension-to-update-values-if-condition-is-met/66605017?noredirect=1#comment117750074_66604932), btw). That's a quite unusual loop in Python, though, as you're ignoring the original elements. I wouldn't call that "normal". The "usual" normal for-loops *building* a list (i.e., same job as a list comp) *are* slower than the equivalent list comps. – Manuel Mar 13 '21 at 16:24
  • @Manuel Well, the reason for my unusual loop is that the OP wants to mutate `probs`, not create a new list. – M-Chen-3 Mar 13 '21 at 16:43
  • 1
    Yeah yeah, it's totally fine. It's unusual because of the unusual task. It's just that your statement sounds general, as if you're talking not just about the task here, and I'd say in general it's not true. – Manuel Mar 13 '21 at 16:49
  • @Manuel Fair enough, I rephrased my answer a bit. – M-Chen-3 Mar 13 '21 at 16:50
3

I recommend to use Python's fractions module for probability calculations.

Hence forth your solution could be as:

from fractions import Fraction
probs = ["1/9", "1/9", "1/9", "1/9", "1/9", "1/9", "1/9", "1/9", "1/9"]
# rather than integer convert it to Fraction, or simply use fractions only from beginning.
probs = [Fraction(i) for i in probs]  # convert like this
# or use directly as below:
probs = [Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9)]

I believe that in probability you have to perform operation of mathematics operation, so you could do as below:

In [12]: print(probs)
[Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9), Fraction(1, 9)]

In [13]: i = 3

In [15]: new_probs = [Fraction(3, 9) if prob==i else Fraction(8, 9) for prob in probs]

In [16]: print(new_probs)
[Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9)]

Or let's say you are actually performing operation of 1 - Probability and multiplying 3 to match, then it would still work with fraction with operation as you expect to be perform with probability functions:

In [17]: new_probs = [3*prob if prob==i else 1-prob for prob in probs]

In [18]: print(new_probs)
[Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(2, 3), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9), Fraction(8, 9)]
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Gahan
  • 4,075
  • 4
  • 24
  • 44
2

Using enumerate()

new_probs = ['3/9' if i == indx else '8/9' for indx, val in enumerate(probs)]
print(new_probs)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Rima
  • 1,447
  • 1
  • 6
  • 12