在Python中计数和分组

时间:2016-01-22 09:02:29

标签: python python-2.7 count

我正在研究一个问题,我必须编写一个程序来计算厨师准备所需的每个项目的数量。客户可以订购的商品有:沙拉,汉堡包和水。 salad:[# salad] hamburger:[# hamburger] water:[# water]例如If order = "hamburger water hamburger",然后该函数返回"salad:0 hamburger:2 water:1"

我的代码是:

def ite(order,item):
    v=order.split()
    t=[]
    for salad in v:
        if salad==item:
            t.append(item)
            v.remove(item)
    return len (t)

def item_order(order):
    s=ite(order,'salad')
    h=ite(order,'hamburger')
    w=ite(order,'water')
    x='salad:%s hamburger:%s water:%s' %(s,h,w)
    return x

但是当我们输入item_order('water water water')时,我的程序会打印

salad:0 hamburger:0 water:2  

而不是

salad:0 hamburger:0 water:3

如果没有两个连续的单词,它可以正常工作。我怎么能纠正这个?

4 个答案:

答案 0 :(得分:4)

解决方案

您可以使用collections.Counter

from collections import Counter

def item_order(order, items=('salad', 'hamburger', 'water')):
    counter = Counter(order.split())
    return ' '.join(['{}: {}'.format(item, counter.get(item, 0)) for item in items])

print(item_order('water water water'))
print(item_order('water salad, salad'))
print(item_order('water hamburger'))

测试它:

print(item_order('water water water'))
print(item_order('water salad, salad'))
print(item_order('water hamburger'))

打印:

salad: 0 hamburger: 0 water: 3
salad: 1 hamburger: 0 water: 1
salad: 0 hamburger: 1 water: 1

说明

这些项目是默认参数:

def item_order(order, items=('salad', 'hamburger', 'water')):

这使得该功能更加灵活,因为您可以根据需要提交其他项目:

def item_order(order, items=('salad', 'fruit', 'water')):

这里有意使用元组,因为列表等可变默认参数可能会导致无意的副作用。这里没问题但可能是一般的花瓶。

将白色空格处的输入字符串拆分为列表后,Counter将创建一个新的counter实例:

counter = Counter(order.split())

例如:

>>> Counter('water water salad'.split())
Counter({'salad': 1, 'water': 2})

最后,列表理解有助于创建一个新的字符串:

' '.join(['{}: {}'.format(item, counter.get(item, 0)) for item in items])

' '.join从字符串列表中创建一个新字符串,其中列表元素由空格分隔。例如:

>>> ' '.join(['abc', 'xyz', 'uvw'])
'abc xyz uvw'

如果密钥在其中,Python字典的方法get()将返回密钥的值,否则返回默认值。例如:

>>> d = {'a': 100, 'b': 200}
>>> d.get('a', 0)
100
>>> d.get('x', 0)
0

将此默认值设置为0,为订单中未包含的项目提供零计数:

counter.get(item, 0))

最后,format()方法有助于将计数值放在字符串中。例如:

>>> '{}: {}'.format('abc', 10)
'abc: 10'

答案 1 :(得分:2)

你不应该做

v.remove(salad)

删除该行,它将解决您的问题。

In [18]: def ite(order,item):
             v=order.split()
             t=[]                        
             for salad in v:
                 if salad==item:
                     t.append(item)
             return len(t)         

In [19]: item_order('salad salad water')
Out[19]: 'salad:2 hamburger:0 water:1'

In [20]: item_order('salad water salad')
Out[20]: 'salad:2 hamburger:0 water:1'

In [21]: item_order('salad water hamburger')
Out[21]: 'salad:1 hamburger:1 water:1'

为什么它不能用于背靠背复制元素是因为在Python中迭代序列并不会隐式地复制列表。该列表将被修改。您可以通过v [:],

制作副本
In [98]: def ite(order,item):
    v=order.split()
    t=[]
    for salad in v[:]:
        if salad==item:
            t.append(item)
            v.remove(item)
    return len(t)

答案 2 :(得分:2)

在迭代时你不应该使用t.remove()。但为什么? 我试图模拟你的问题

t = ['a', 'b', 'c']
it = iter(it)  # for loop internally use iter() to iterate
it.next()      # it should print 1st element of list which is 'a'
t.remove('a')  #Now list t becomes ['b', 'c']
it.next()      # it should print 2nd element of list which is 'c'
t.remove('b')  #Now list t becomes ['c']
it.next()      #it should print 3rd element of list, But list has only one element
# It throws exception - "StopIteration"

此异常由"处理"静静地循环,所以" for"循环不会迭代第3个元素。

答案 3 :(得分:0)

在迭代它时改变列表通常是一个坏主意 - 即你删除了python已经迭代过的项目吗?

list对象有一个可能有帮助的count方法!

split_order = order.split(" ")
salads = split_order.count('salad')

https://docs.python.org/2/tutorial/datastructures.html