Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

How do I improve this function?

I've made a function that reorders a list, and I'm wondering if there's an easier/better way to do it?

It takes an argument that would be a user input string of numbers representing the new list item order, such as: "1,4,2,5,3". It then strips the commas and splits it into a list such as ["1", "4", "2", "5", "3"] so that it can be looped through.

Note: I used copy.copy() to make changes to a copy of the list within the loop, then updated the main list to the copy at end, otherwise the items ended up in the wrong order for some reason!

Here's the code:

import copy
current_lists = [ {'test1':[]}, {'test2':[]}, {'test3':[]}, {'test4':[]}, {'test5':[]} ]

def reorder_lists(new_list_position):
    split_list = new_list_positions.split(",")
    working_list = copy.copy(current_lists)
    count = 0
    for item in split_test:
        item_to_insert = current_lists[int(item) - 1]
        working_list.remove(item_to_insert)
        working_list.insert(count, item_to_insert)
        count += 1
    current_lists = working_list

So if run with:

test_user_input = "1,4,2,5,3"
reorder_lists(test_user_input)
print(current_lists)

it shows: [ {'test1':[]}, {'test4':[]}, {'test2':[]}, {'test5':[]}, {'test3':[]} ]

4 Answers

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

Ok-- I get what you are looking for. Megan's suggestion of the enumerate function is a good one.

If you need this to fit a "functional programming paradigm" you would not want to reference a global variable in the function and be aware that the programmer could pass an immutable list so you would always want to create a new list.

current_list = ["test1", "test2", "test3", "test4", "test5"]
user_input = "5,3,1,4,2"

def reorder_list(user_list, user_order):
    sorted_list = user_list[:]
    for idx, item in enumerate(user_order.split(",")):
        sorted_list[idx] = user_list[int(item)-1]
    return sorted_list

print("Before")
print(current_lists)
sorted_list = reorder_list(current_list, user_input)
print("After")
print(sorted_list)

or if you a masochist, you can do this as a list comprehension in one line! Definitely not Pep20 inspired.

sorted_list = [current_list[i] for i in [int(x)-1 for x in user_input.split(',')]]
Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

Do you mean something like this?

test_user_input = "1,4,2,5,3"

# create a new list based on the split string.
newlist = test_user_input.split(',')

# sorting in-place
newlist.sort()
print(newlist)

# can also sort in the reverse direction
newlist.sort(reverse=True)
print(newlist)

Thanks Jeff, but I meant that the user input is the order that they want the items of the list to be. I think I complicated it by having dicts in the list, but if a list was: ["test1", "test2", "test3", "test4", "test5"] And the user input was "5,3,1,4,2", then the list would be changed to: ["test5", "test3", "test1", "test4", "test2"]

Megan Amendola
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree seal-36
Megan Amendola
Treehouse Teacher

Instead of using a count, you could instead use enumerate to get both an index and the item in your iterable.

for count, item in enumerate(split_test):
        item_to_insert = current_lists[int(item) - 1]
        working_list.remove(item_to_insert)
        working_list.insert(count, item_to_insert)

Thanks Megan, I'll look into enumerate now!

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

Just in case you were looking to sort the dictionary objects that had list strings.

current_lists = [{'test1':'4,6,3,1'}, {'test2':'9,3,2,1'}]

def reorder_lists_alt(user_lists, reverse=False):
    sorted_lists = []
    for obj in user_lists:
        if not isinstance(obj, dict):
            continue
        for key, lst in obj.items():
            if isinstance(lst, str):
                newlist = lst.split(',')
                newlist.sort(reverse=reverse)
                sorted_lists.append({key:newlist})
    return sorted_lists

print("Before")
print(current_lists)
sorted_lists = reorder_lists_alt(current_lists)
print("After")
print(sorted_lists)
print("Reversed lists")
sorted_lists_reversed = reorder_lists_alt(current_lists, reverse=True)
print(sorted_lists_reversed)
Before
[{'test1': '4,6,3,1'}, {'test2': '9,3,2,1'}]
After
[{'test1': ['1', '3', '4', '6']}, {'test2': ['1', '2', '3', '9']}]
Reversed lists
[{'test1': ['6', '4', '3', '1']}, {'test2': ['9', '3', '2', '1']}]

This is pretty useful for the future, cheers!