按顺序有效地对列表进行排序

时间:2017-05-22 18:17:04

标签: python python-3.x

假设我有两个清单:

sequence = [25, 15, 20, 15, 25, 25]
l = [(25, 'banana'), 
     (25, 'apple'), 
     (25, 'pine'), 
     (20, 'soap'), 
     (15, 'rug'), 
     (15, 'cloud')]

我想按顺序排序第二个列表l。 在示例中,数字25出现多次,在这种情况下,只要它具有值25,那么哪个元组在该位置并不重要。 列表的长度始终相同。

我目前的做法是:

r = list(range(len(sequence)))

for i, v in enumerate(sequence):
    for e in l:
        if e[0] == v:
            r[i] = e
            l.remove(e)
print(r)

可能的输出:

  

[(25,' banana'),      (15,' rug'),      (20,'肥皂'),      (15,'云')      (25,' apple'),      (25,'松')]

你认为有更好的方法吗?

感谢您的帮助!

莫夫

5 个答案:

答案 0 :(得分:5)

是。首先创建一个默认的dictonary,数字作为键,并命名为每个键的值(作为列表)

private TextField<String> addValueDatePickerNew(final MarkupContainer parent, final String id, final IModel<String> model)
{
    final TextField<String> result = new TextField<String>(id, model) {
        private static final long serialVersionUID = 1L;

        @Override
        protected void onConfigure()
        {
            setVisibilityAllowed(true);
            setRequired(true);
        }

        @Override
        protected void onComponentTag(ComponentTag tag) 
        {
            super.onComponentTag(tag);
            String jsDateField = "{console.log('From ReportFilterValueEditor');}";
            tag.put("onload", jsDateField);
        }
    };

    result.setOutputMarkupId(true);
    parent.add(result);
    return result;
}

然后,迭代序列并使用sequence = [25, 15, 20, 15, 25, 25] l = [(25, 'banana'), (25, 'apple'), (25, 'pine'), (20, 'soap'), (15, 'rug'), (15, 'cloud')] from collections import defaultdict d = defaultdict(list) for i,n in l: d[i].append(n) 从相关列表(匹配号码)中删除一次删除一个项目(每个列表中必须有足够的项目,并且键必须在那里,或者你' ll得到一个python异常(空列表/键错误)):

list.pop

结果:

result = [(i,d[i].pop()) for i in sequence]
print(result)

订单与预期输出不同,但数字与名称匹配,这就是重点。如果你想要相同的订单,只需删除第一个项目(列表中的性能较低,所以如果你有选择,最好插入和删除列表中最后一个项目,它会更快):

[(25, 'pine'), (15, 'cloud'), (20, 'soap'), (15, 'rug'), (25, 'apple'), (25, 'banana')]

给出:

result = [(i,d[i].pop(0)) for i in sequence]

答案 1 :(得分:4)

另一种选择是使用键功能进行排序,该功能将从sequence中删除已使用的元素(此方法会修改sequence,因此如果稍后需要sequence,则应创建副本:

sequence = [25, 15, 20, 15, 25, 25]
l = [(25, 'banana'), 
     (25, 'apple'), 
     (25, 'pine'), 
     (20, 'soap'), 
     (15, 'rug'), 
     (15, 'cloud')]

def key_func(_tuple):
    idx = sequence.index(_tuple[0])
    sequence[idx] = None
    return idx

l.sort(key=key_func)

正如Jared Goguen所说,如果您需要保留sequence,下一个包装器会有所帮助:

def get_key_func(sequence):
    sequence_copy = sequence[:]
    def key_func(_tuple):
        idx = sequence_copy.index(_tuple[0])
        sequence_copy[idx] = None
        return idx
    return key_func

l.sort(key=get_key_func(sequence))

答案 2 :(得分:3)

我的想法与Jean相似,但我使用list迭代器而不是pop方法(如果从前面弹出,则在O(n)中运行,但在O(1)中如果你从最后弹出。)

>>> from collections import defaultdict
>>> supply = defaultdict(list)
>>> for k, v in l:
...     supply[k].append(v)
... 
>>> supply_iter = {k:iter(v) for k,v in supply.items()}
>>> [(k, next(supply_iter[k])) for k in sequence]
[(25, 'banana'), (15, 'rug'), (20, 'soap'), (15, 'cloud'), (25, 'apple'), (25, 'pine')]

next方法还允许使用可选的默认值作为第二个参数(None在这里是个不错的选择。)

答案 3 :(得分:1)

你可以在循环之前没有设置数组而没有枚举。 我不认为它更快但可能更容易理解:

r =[]

for val in sequence:
    for key, elem in l:
        if key == val:
            temp = (val, elem)
            r.append(temp)
            l.remove(temp)
            break # break the loop thru element to avoid having 2 elements of the same "key"
print(r)

答案 4 :(得分:0)

另一种方法,

sequence = [25, 15, 20, 15, 25, 25]
list1 = [(25, 'banana'), 
     (25, 'apple'), 
     (25, 'pine'), 
     (20, 'soap'), 
     (15, 'rug'), 
     (15, 'cloud')]
     
_dict = {}

# organised duplicates into dict
for a, b in list1 :
    _dict.setdefault(a, []).append(b)

print(_dict)

index_list = []

# append based on sequence using pop to avoid duplicates 
for key in sequence:
    next_in_line = _dict[key].pop(0)
    index_list.append((key, next_in_line))
   
print(index_list)

给予

{25: ['banana', 'apple', 'pine'], 20: ['soap'], 15: ['rug', 'cloud']}
[(25, 'banana'), (15, 'rug'), (20, 'soap'), (15, 'cloud'), (25, 'apple'), (25, 'pine')]

[Program finished]