假设我有两个清单:
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,'松')]
你认为有更好的方法吗?
感谢您的帮助!
莫夫
答案 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]