mortysporty
mortysporty

Reputation: 2889

Sort list and force certain elements to be first

I have a list of column names, name_columns. The list contains a subset of special column names, as well as non-special column names. The special column names are stored in the list special_columns. I want to sort name_columns so that the special column names appear first in the sorted list, in the order they are listed in special_columns.

The order of the non-special column names is really not that important, as long as they appear after the special columns.

Example

special_columns = ['from_date', 'to_date', 'id_1', 'id_2', 'id_3', 'id_4']
name_columns = ['a', 'id_2', 'from_date', 'to_date', 'id_4', 'c']

#Do some smart sorting
#After sorting
name_columns = ['from_date', 'to_date', 'id_2', 'id_4', 'a', 'c']

I have mulitple list's like name_columns and they all contain various subset (including none) of special_columns. Any suggestions on how this can be achieved?

Upvotes: 1

Views: 1927

Answers (5)

Aaditya Ura
Aaditya Ura

Reputation: 12679

In one line you try :

special_columns = ['from_date', 'to_date', 'id_1', 'id_2', 'id_3', 'id_4']
name_columns = ['a', 'id_2', 'from_date', 'to_date', 'id_4', 'c']


new=[]
final=[[new.append(item),name_columns.remove(item)]  for item in special_columns if item in name_columns]

new.extend(name_columns)

print(new)

Detailed solution:

ordered=[]
for item in special_columns:
    if item in name_columns:
        ordered.append(item)
        name_columns.remove(item)


ordered.extend(name_columns)
print(ordered)

output:

['from_date', 'to_date', 'id_2', 'id_4', 'a', 'c']

Upvotes: 1

PM 2Ring
PM 2Ring

Reputation: 55479

One way to do this is to create a dict that contains the order info of the special items. Creating a dict beforehand is much more efficient than calling the .index method on every item that you want to sort. The trick is to assign zero to the non-special items, and negative numbers to the special items, and then sort in reverse, so that the non-special items will always come at the end of the sorted list.

special_columns = ['from_date', 'to_date', 'id_1', 'id_2', 'id_3', 'id_4']
name_columns = ['a', 'id_2', 'from_date', 'to_date', 'id_4', 'c']

special_order = {u: i for i, u in enumerate(reversed(special_columns), 1)}
name_columns.sort(key=lambda s: special_order.get(s, 0), reverse=True)
print(name_columns)

output

['from_date', 'to_date', 'id_2', 'id_4', 'a', 'c']

Upvotes: 1

Ma0
Ma0

Reputation: 15204

How about like this:

special_columns = ['from_date', 'to_date', 'id_1', 'id_2', 'id_3', 'id_4']
name_columns = ['a', 'id_2', 'from_date', 'to_date', 'id_4', 'c']

temp2 = set(name_columns).difference(special_columns)
sorted_cols = [a for a in special_columns if a in name_columns] + sorted(list(temp2))
#             \_____________________1________________________/    \_______2_________/
print(sorted_cols)  # ['from_date', 'to_date', 'id_2', 'id_4', 'a', 'c']

Two parts to the answer:

  1. List-comprehension that loops thought the special names and stores them in the result if they exist in the name_column.
  2. Set operations to handle all elements of name_column that are not special

Few remarks:

  1. if ordering of the non-special items is not important, you can remove the sorted() call on list(temp2) to speed up the code.
  2. defining temp2 is of course not required.

Upvotes: 3

v100ev
v100ev

Reputation: 186

Do you need really to sort the list? You could just create a new "sorted" one and use it. Something like:

special_columns = ['from_date', 'to_date', 'id_1', 'id_2', 'id_3', 'id_4']
name_columns = ['a', 'id_2', 'from_date', 'to_date', 'id_4', 'c']
a = []


for el in name_columns:
    if el in special_columns:
        a.insert(0, el)#insert in the beggining of the resulting list
    else:
        a.append(el)

print a
['id_4', 'to_date', 'from_date', 'id_2', 'a', 'c']

Upvotes: 1

Sebastian Wozny
Sebastian Wozny

Reputation: 17506

Try using a key function as an argument for sorted:

>>> special_columns = ['from_date', 'to_date', 'id_1', 'id_2', 'id_3', 'id_4']
>>> name_columns = ['a', 'id_2', 'from_date', 'to_date', 'id_4', 'c']
>>> print(sorted(name_columns,key=lambda x: special_columns.index(x) if x in special_columns else 10e99))

['from_date', 'to_date', 'id_2', 'id_4', 'a', 'c']

Upvotes: 1

Related Questions