根据Python中的条件求和嵌套列表

时间:2016-12-10 10:08:54

标签: python list nested

我有一个嵌套列表,如下所示:

[['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
 ['London','2014',4800,70,90],['Bern','2013',300,450,678], 
 ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]]

如果城市和年份相等,我想要做的是将子列表中的每个整数值与另一个子列表相加。我首先想到的是一本以城市和年份为关键字典的词典,但却导致排序问题。

然后我有:{('Vienna','2012'):[890,503,70],('Bern','2013'):[800,1150,768],...}

我也试过这样的事情:

[sum(x) for x in zip(*list) if x[0] == x[0]]但当然没有用。

我可以使用嵌套列表执行此类操作,以便按城市和年份对其进行排序会更容易吗?

6 个答案:

答案 0 :(得分:2)

您可以构造一个结果dict,其中key是原始列表中前两个项的元组,值是list个数字。每次向dict添加值时,都可以使用get返回现有元素或给定默认值,在本例中为空列表。

在您要添加现有列表和列表后,您可以使用zip_longestfillvalue来获取两个列表中要求的数字。 zip_longest返回长度为2的元组,每个列表包含一个数字。如果一个列表长于其他fillvalue用作默认值,那么这也适用于列表具有不同长度的情况。最后,列表理解可用于对每个项目求和一个新值:

from itertools import zip_longest

l = [
    ['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
    ['London','2014',4800,70,90],['Bern','2013',300,450,678],
    ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]
]

res = {}
for x in l:
    key = tuple(x[:2])
    res[key] = [i + j for i, j in zip_longest(res.get(key, []), x[2:], fillvalue=0)]

print(res)

输出:

{('Vienna', '2013'): [700, 850, 90], ('London', '2014'): [10200, 949, 168], 
 ('Vienna', '2012'): [890, 503, 70], ('Bern', '2013'): [800, 1150, 768]}  

如果您想要按字母顺序对城市进行排序,请先将最近年份排序,然后将自定义key传递给sorted

for item in sorted(res.items(), key=lambda x: (x[0][0], -int(x[0][1]))):
    print(item)

输出:

(('Bern', '2013'), [800, 1150, 768])
(('London', '2014'), [10200, 949, 168])
(('Vienna', '2013'), [700, 850, 90])
(('Vienna', '2012'), [890, 503, 70])

答案 1 :(得分:1)

您只需使用字典将所有国家/地区名称和年份存储为一个值,即可获得所需的结果。字典中的每个键都是国家名称和相应年份的元组。

例如:key = (country,year)

这使我们拥有分组时所需要的唯一值。

L = [
        ['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
        ['London','2014',4800,70,90],['Bern','2013',300,450,678],
        ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]
    ]

    countries = {}

    for list in L:
        key = tuple(list[0:2])
        values = list[2:]
        if key in countries:
            countries[key] = [sum(v) for v in zip(countries[key],values)]
        else:
            countries[key] = values

    print(countries)

退出:

 {
     ('Vienna', '2012'): [890, 503, 70],
     ('London', '2014'): [10200, 949, 168],
     ('Bern', '2013'): [800, 1150, 768],
     ('Vienna', '2013'): [700, 850, 90]
}

答案 2 :(得分:0)

您应该按照问题中的概述维护字典。这样的事情会有所帮助,

cities = {}
for a in list:
    city_key = a[:1]
    if city_key in cities:
        cities[city_key] = [a + b for a, b in zip(a[2:], cities[city_key])]
    else:
        cities[city_tuple] = a[2:]

答案 3 :(得分:0)

一种方法是通过您想要的密钥(城市和年份)将列表列表拆分为字典。此外,defaultdict有助于将所有距离压缩成平面列表

>>> from collections import defaultdict
>>> dct = defaultdict(list)
>>> for item in lst:
...    dct[(item[0], item[1])].extend(item[2:])

现在dct具有按城市和年份分组的整数:

>>> dct
defaultdict(<type 'list'>, {('Vienna', '2013'): [700, 850, 90], ('London', '2014'): [5400, 879, 78, 4800, 70, 90], ('Vienna', '2012'): [890, 503, 70], ('Bern', '2013'): [300, 450, 678, 500, 700, 90]})

你可以总结一下:

>>> for key in dct:
...    print(key, sum(dct[key]))
... 
(('Vienna', '2013'), 1640)
(('London', '2014'), 11317)
(('Vienna', '2012'), 1463)
(('Bern', '2013'), 2718)

答案 4 :(得分:0)

import akka.actor.{Actor, ActorRef}
import akka.pattern._

class Registry extends Actor {
  import Registry._
  var registry:Map[String, Any] = Map()
  def receive = {
    case Lookup(name) => sender ! registry.get(name)
  }
}

object Registry {
  import akka.actor.{ActorSystem, Props}
  case class Lookup(name: String)  
  // create dedicated actor infrastructure
  val system = ActorSystem("myActorInfrastructure")
  // create actor with a name and register it with the infrastructure
  def apply(name: String) = system.actorOf(Props(new Registry()), name) 
}

class Tweeter(val name: String, val regist:Registry, var followers:List[ActorRef]=List()) extends Actor{
    import Tweeter._
    def receive = {
      case Follow(user) => {
        //Here is the error
        (regist!? Lookup(name)) match{
        case Some(a:ActorRef) => a ! AddFollower(sender)
        }
      }
      case AddFollower(follower) => followers = follower::followers 
  }
}

object Tweeter {
    import akka.actor.{ActorSystem, Props}
  case class Follow(user: String)
  case class AddFollower(follower: ActorRef)
  def apply(name: String, annuaire:Registry) = Registry.system.actorOf(Props(new Tweeter(name,annuaire))) 
}

out:

nl = [['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
      ['London','2014',4800,70,90],['Bern','2013',300,450,678],
      ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]]
d = {}
for l in nl:
    key = l[0] , l[1]
    value = l[2:]
    if key not in d:
        d[key] = value
    else:
        d[key] = [sum(i)for i in zip(d[key], value)]
print(d)

答案 5 :(得分:0)

使用itertools.groupbyoperator.itemgetter函数的解决方案:

import itertools, operator

l = [['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
 ['London','2014',4800,70,90],['Bern','2013',300,450,678],
 ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]]

getter = operator.itemgetter(0, 1)  # the sequence to be grouped(first two items)
summed = [[k[0],k[1],sum(sum(d[2:]) for d in list(group))]
          for k, group in itertools.groupby(sorted(l, key=getter), getter)]

print(summed)

输出:

[['Bern', '2013', 2718], ['London', '2014', 11317], ['Vienna', '2012', 1463], ['Vienna', '2013', 1640]]