remove all values from multiple lists at same index position with some logic
I'm a beginner in programming an开发者_如何学Cd also a beginner in Python. Below are the details for a better understanding of my issue.
Rooms = ['BlueRoom', 'RedRoom', 'GreenRoom', 'BlueRoom']
Availability = [5, 7, 3, 5]
Description = ['Blue', 'Red', 'Green', 'Blue']
Price = [120, 90, 150, 115]
What I need to have is, the same lists, but with the BlueRoom and all of the values in the same index position of the lists with the highest price removed, like this:
Rooms = ['RedRoom', 'GreenRoom', 'BlueRoom']
Availability = [7, 3, 5]
Description = ['Red', 'Green', 'Blue']
Price = [90, 150, 115]
I would really appreciate if someone could help me. This lists are just for example, but the lists I have to handle will have several rooms that are duplicated and I will have to do the same with each one.
EDIT: First of all, thank you all for the quick answers. On the other hand, I forgot to mention a little, but not less important at all, detail. I have to code using a very old interpreter, Jython version 2.2. So, some functions may not work for me.
As Jochen pointed out in a comment, you're probably better off writing a class to store your information. Each instance of a class can store all the information relating to a single room.
class Room(object):
def __init__(self, name, availability, description, price):
self.name = name
self.availability = availability
self.description = description
self.price = price
rooms = [Room('BlueRoom', 5, 'Blue', 120), ...]
This way, all the information about a single room is always kept together, and you don't have to worry about keeping different lists in sync. So you can just search the list to find the duplicate rooms and remove the ones you don't want.
For example, suppose you want to only keep the lowest-priced room matching a given description. The way I'd do that is
import itertools
# here is where you might insert the class code from above
def namekey(room):
return room.name
def pricekey(room):
return room.price
sorted_rooms = sorted(rooms, namekey)
First, you will need to sort the list rooms by name, in order for to the following code to work.
cheapest_rooms = []
That creates a new list that we'll fill with the cheapest room with each name.
for name, group in itertools.groupby(sorted_rooms, namekey):
This will split the list of rooms into sub-lists by name.
cheapest = min(group, key=pricekey)
This finds the cheapest room out of the group.
cheapest_rooms.append(cheapest)
And that appends it to the list.
All this can be condensed into
import itertools
# here is where you might insert the class code from above
def namekey(room):
return room.name
def pricekey(room):
return room.price
[min(group, key=pricekey) for name, group \
in itertools.groupby(sorted(rooms, namekey), namekey)]
Rooms = ['BlueRoom', 'RedRoom', 'GreenRoom', 'BlueRoom']
Availability = [5, 7, 3, 5]
Description = ['Blue', 'Red', 'Green', 'Blue']
Price = [120, 90, 150, 115]
highest_price = max(Price)
x = Price.index(highest_price)
list = [Rooms,Availability,Description,Price]
for item in list:
del item[x]
print Rooms
print Availability
print Description
print Price
I think that does what you need. :D
-EDIT- It finds the highest value in Price. Finds the index of that value, then removes that index from all of the lists. -EDIT-
For dealing with parallel lists like that, I would recommend using zip
:
room_data = zip(Rooms, Availability, Description, Price)
room_data[0]
-> ('BlueRoom', 5, 'Blue', 120)
Then you can do some logical processing on that list:
blue_rooms = [r for r in room_data if r[0] == 'BlueRoom']
best_blue_room = max(blue_rooms, key=lambda (r,a,d,p): p)
room_data.remove(best_blue_room)
Rooms, Availability, Description, Price = map(list, zip(*room_data))
Maybe consider working directly on room_data
instead of converting it back and forth like in the last line above...
You can get a subset of a list, called a “slice”, by specifying two indices. The return value is a new list containing all the elements of the list, in order, starting with the first slice index , up to but not including the second slice index. If you leave out the second index it continues to the end of the list e.g.
Rooms = Rooms[1:]
Rooms would then equal
Rooms = ['RedRoom', 'GreenRoom', 'BlueRoom']
CurrentRoom = Rooms.pop(0)
would take the first item off the list and save it in CurrentRoom. If you don't need to retain or use it, just Rooms.pop(0)
I really encourage you to use a different solution, what you want to do, I think is possible but it doesn't elegant and maintainable.
I think is better if you create one class to represent your Rooms and work with only one list of Rooms.
Firstly, a direct answer to your question: you can remove an element in place from a list by index using del list_name[index]
, or in your example del Rooms[0]
. There is no one liner using this technique to remove the same same indexed element from all four lists. It takes four del
statements.
If your question is about the logic of finding the index of highest priced item, then the thing to do goes like this (presented in pythony pseudo code):
idx_of_highest = 0
for i in range(Price.length()):
if Price[i] > Price[idx_of_highest]:
idx_of_highest = i
del Room[i]
del Price[i]
del Description[i]
del Availability[i]
This assumes your lists are not sorted by price, and are essentially in random order. If not, the highest price is either the first or last index.
Secondly, you might want to consider using a list of dictionaries in this case, or even a list of classes is you've got that far.
Edit: If you don't know what "in place" means, it means the list itself is modified permanently, i.e. you are not obtaining a copy or partial copy (slice). If you want copies of the lists, then the easiest way is to use slice notation, e.g. to get a copy of a list with the n'th element removed use list_name[0:n]+list_name[n+1:]
instead of a del statement. Assign the result to variable of your choice, as in new_rooms = rooms[0:i]+rooms[i+1:]
精彩评论