在python关联列表中有效地查找元素

1 python list-comprehension list

我有一组看起来像这样的列表:

conditions = [
["condition1", ["sample1", "sample2", "sample3"]],
["condition2", ["sample4", "sample5", "sample6"],
...]
Run Code Online (Sandbox Code Playgroud)

如何在Python中高效优雅地完成以下事项?

  1. 找到某种条件下的所有元素?

    例如,获取条件2中的所有样本.现在我可以这样做:

    for cond in conditions:
      cond_name, samples = cond
      if cond_name == requested_cond:
        return samples
    
    Run Code Online (Sandbox Code Playgroud)

    但那很笨重.

  2. 找到条件列表的有序联合?例如ordered_union(["condition1", "condition2"], conditions) 应该返回:

    ["sample1", "sample2", "sample3", "sample4", "sample5", "sample6"]
    
    Run Code Online (Sandbox Code Playgroud)

我怎样才能在Python中高效地完成这项工作?可能有一个聪明的单线?

Tim*_*ker 6

这看起来更像是一个工作dict:

conditions = {
"condition1": ["sample1", "sample2", "sample3"],
"condition2": ["sample4", "sample5", "sample6"],
...}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用"订购联盟"

>>> conditions["condition1"]+conditions["condition2"]
['sample1', 'sample2', 'sample3', 'sample4', 'sample5', 'sample6']
Run Code Online (Sandbox Code Playgroud)

在Python 3.1或2.7中,您可以使用以下内容保留订单OrderedDict:

from collections import OrderedDict
conditions = OrderedDict([
["condition1", ["sample1", "sample2", "sample3"]],
["condition2", ["sample4", "sample5", "sample6"]]
])
Run Code Online (Sandbox Code Playgroud)

然后你可以获得"有序联合",也可以OrderedDicts是任意大小:

>>> import itertools
>>> [item for item in itertools.chain(*conditions.values())]
['sample1', 'sample2', 'sample3', 'sample4', 'sample5', 'sample6']
Run Code Online (Sandbox Code Playgroud)

  • 这假设样本名称可以像这样按字母顺序排序,这在我的示例中恰好是正确的,但在我的代码中通常并不正确 - 对于这种混乱,我们深表歉意。condition1 可以称为 foo,condition2 可以称为 bar,其中的样本可以以不易排序的方式任意命名。 (2认同)

Ale*_*lli 5

好吧,如果你被迫保留那个笨重的数据结构,你就不能期望太多。第一个解决方案的单行代码将类似于:

def samplesof(requested_cond, conditions):
    return next(s for c, s in conditions if c==requested_cond)
Run Code Online (Sandbox Code Playgroud)

对于第二个,如果你坚持说俏皮话,那就是这样的:

def ordered_union(the_conds, conditions):
    return [s for c in the_conds for s in samplesof(c, conditions)]
Run Code Online (Sandbox Code Playgroud)

有更快的方法来解决第二个问题,但它们都是多行的,例如:

aux_set = set(the_conds)
samples_by_cond = dict((c, s) for c, s in conditions if c in aux_set)
return [s for c in the_conds for s in samples_by_cond[c]]
Run Code Online (Sandbox Code Playgroud)

请注意,后一种方法更快的关键在于它使用了正确的数据结构(集合和字典)——不幸的是它必须自己构建它们,因为传入的嵌套列表实际上conditions是错误的数据结构。

难道你不能封装conditions为一个类的成员变量,只构建一次关键的(正确的,快速的)辅助数据结构吗?例如:

class Sensible(object):
  def __init__(self, conditions):
    self.seq = []
    self.dic = {}
    for c, s in conditions:
      self.seq.append(c)
      self.dic[c] = s
  def samplesof(self, requested_condition):
    return self.dic[requested_condition]
  def ordered_union(self, the_conds):
    return [s for c in the_conds for s in self.dic[c]]
Run Code Online (Sandbox Code Playgroud)

现在既快速又优雅!

我假设您需要self.seq其他东西(条件序列)(您提到的两个操作当然不需要!),并且该序列和示例中没有重复(无论您的实际规格是什么)不会很难适应,但是当你没有提到它们时盲目地试图猜测它们是非常困难和毫无意义的;-)。