Need help for an exercise (python 3)

Hi Everyone.

I need a little bit of help with an exercise I am doing at the moment.
I would like to know how to , for every integer inferior to 10 ,create a couple looking like this :
[i, [a, b, c, ….]] where [a, b, c, …] corresponds to the positions of i in the following list :
L = [3, 2, 3, 1, 2, 0, 9, 9, 9, 2, 3]
And for practical reasons, I want the result to look like this :
[[0, [5]], [1, [3]], [2, [1, 4, 9]], [3,[0, 2, 10]], [4, ], [5, ], [6, ], [7, ], [8, ], [9, [6, 7, 8]]]
The problem is that I have no idea about how to do this. Can somebody help me please ?

@FroZ
First of all, this is the not right place to ask for this type of question. There are several forums and of course StackOverflow that are more suitable.
Having said that, I couldn’t resist offering a solution, with two list comprehensions.

res = [[i, [j for j, v in enumerate(L) if v == i]] for i in range(10)]
1 Like

Sorry Ruud, I disagree that “this is the not right place to ask for this
type of question”. It’s a question about Python, by and for users of
Python. If it is not appropriate, what sort of question would be
appropriate? (That’s not a rhetorical question.)

Of course you are correct that there are other forums which may be
better or more appropriate for a beginner, such as the tutor mailing
list or Reddit’s learnpython subreddit:

https://old.reddit.com/r/learnpython/

https://mail.python.org/mailman/listinfo/tutor

Teddy, when you have no idea how to solve a programming problem, often a
good start is to work through the exercise with pen and paper, writing
down exactly what steps you took as if you were writing instructions
for a child, or a recipe. Then translate each step into Python code.

3 Likes

Thank you both for the quick response !

Sorry to bother you again but I need your help again with an exercise I’m doing right now :frowning:
I would like to know, how, for each e element of the list L = [3, 2, 3, 1, 2, 0, 9, 9, 9, 2, 3]
create a couple like : [e, [a, b, c, ….]] where [a, b, c, …] corresponds to the positions of e in the list L.
And for practical reasons, I need this to look like this :
[[3, [0, 2, 10]], [2, [1, 4, 9]], [1, [3]], [0, [5]], [9, [6, 7, 8]]]

I tried to resolve this by drawing this on a paper but I am totally blocked…

You have a list like this:

L = [3, 2, 3, 1, 2, 0, 9, 9, 9, 2, 3]

Start with the first item, 3, at position 0 in the list.

Walk through the list, and write down the position if the element in
that position is the same as the element we are looking at, 3:

Position 0: does 3 equal 3? Yes it does, write down 0.
Position 1: does 3 equal 2? No.
Position 2: does 3 equal 3? Yes, write down 2.
...
Position 9: does 3 equal 2? No.
Position 10: does 3 equal 3? Yes, write down 10.

Now we move on to the next element in the list, 2, and do the same
thing:

Position 0: does 2 equal 3? No.
Position 1: does 2 equal 2? Yes, write down 1.
...

And so on, until you have done the entire list.

Is that clear?

Whenever you have to “do the same thing” multiple times, it makes sense
to write a function. So let’s start with a function that takes an
element as argument, and walks the list L returning the positions:

def collect_positions(element):
    positions = an empty list
    for position, item in enumerate(L):
        does element equal item? if so,
            append position to positions
        (otherwise do nothing)
    return positions

Obviously most of that is not legal Python code, you have to write that
yourself.

Now that we have a function that gives us the positions an element is
seen in, we can easily collect the positions of every element:

def collect_all_positions():
    all_positions = an empty list
    for element in L:
        result = collect_positions(element)
        append (position, result) to all_positions
    return all_positions

If you successfully re-write that into working Python code, you will
discover that the “all positions” part doesn’t do exactly what you
have asked. I will leave the difference, and fixing it, as an exercise.

(Once you have the rest working, you can ask for a hint if you need it.)

By the way, if this is an exercise for college, your college probably
has hugely strict rules about plagiarism and copying. Ask your college
tutor how much of the help you get here needs to be declared.

1 Like

Hi !

Thank you again for helping me with your answer.
First, I have to say that I’m not in college, I’m trying to learn Python on my own and I am taking exercises everywhere I can on the web.

Then, after your answer, I would like to know if there was a way to reduce all of this into comprehensive lists ? Thank you for taking your time to answer to all my questions.

@FroZ
What about:

res = {}
for j, v in enumerate(L):
    res[v] = res.setdefault(v, []) + [j]
print (list(res.items()))

?

I thought of this :

 X = [[j, [i for i in range(len(L)) if j == L[i] ]] for j in L] 

But I don’t want of the duplications, how can I get rid of them ?

Rather than “get rid of” duplicates, think about avoiding them in the
first place. How would you avoid processing the same value twice?

for element in L:
    if I haven't already processed element:
        process element

How do you check whether you’ve already processed the element? Just look
in the results you are collecting, and see if it’s already there!

Alternatively, you could keep a variable of “already processed”
elements, and check in that.

Details and code are left as an exercise.

I found this as a final result :

X = [[j, [i for i in range(len(L)) if j == L[i] ]] for j in L]
R = []

for i in X :
    if i not in R :
        R.append(i)

@FroZ
As a one liner

X = [[vj, [i for i, vi in enumerate(L) if vj == L[i] ]] for j, vj in enumerate(L) if L[j] not in L[:j]]

I’d strongly advise against such one-liners (when providing help), and instead recommend separating that into multiple individual steps. For several reasons:

  1. Readability - it may be clear to you what is intended, but it takes far more effort from readers to decipher what is going on and to determine its purpose. Not to mention easier to figure it out again yourself when/if you have to look over the code again several months or more later. Without readability, you lose out on one of Python’s strongest advantages.

  2. Maintainability - if you need to change some part of it later down the road, it’s much easier to modify components of it when it’s separated into smaller individual steps.

  3. Debugging - If there’s an issue with the code or it’s not behaving as expected, smaller steps are both easier to understand and easier to implement logging for.

This example may seem small and simple enough that it doesn’t matter, but particularly when helping others it’s important to teach them good coding habits. Even if you understand better, it may not be at all obvious to those you’re providing help/advice to; particularly if they’re new to Python and/or programming in general.

That being said, it’s okay if you do this for a one-liner in the REPL or for a short script that’s never going to be re-used/see the light of day (or for specific, niche purposes), but otherwise I’d generally advise against it.

That’s great! There are many fantastic resources for learning out there, starting with the official tutorial on docs.python.org (which I’d recommend going through if you haven’t already). I personally found programming challenge websites to be particularly helpful and motivating when I was starting out; I still dabble in them occasionally.

By “comprehensive lists”, I assume you’re referring to list comprehension? If so, list comprehension can be an incredibly powerful tool when used correctly, but it can also be misused and lead to bad programming habits (especially when you’re first starting out).

I’d say it’s bested used when you have a single mapping operation (perform an action on every element) and/or a filter (use only the elements that match a certain conditional). But if it gets more complex than that, I’d almost always [1] advise breaking it into multiple steps. I listed some of the advantages of doing so in the above post.

[1] - It can be a bit subjective and based on experience to determine when a list comp is becoming too complex. But in general it’s typically better to keep them simple. Remember: “Simple is better than complex”. There’s really no significant advantage to be gained by cramming a large amount of functionality into a single line of code; if anything, doing so can often lower the quality.