【问题标题】:Grouping Algorithm分组算法
【发布时间】:2014-07-05 07:20:54
【问题描述】:
Fruits = [
 {name:apple, color:red,   taste:good,  price:medium},
 {name:apple, color:red,   taste:bad,   price:medium},
 {name:apple, color:red,   taste:good,  price:low},
 {name:apple, color:red,   taste:bad,   price:medium},
 {name:apple, color:red,   taste:good,  price:medium},
 {name:apple, color:green, taste:bad,   price:medium},
 {name:apple, color:green, taste:bad,   price:medium}
];

在这里,我想计算一种苹果,即红色、味道好且价格中等的苹果,对于这种类型,计数为 2,因此将删除一个对象,并将新的属性计数添加到第一个。

同样,我想计算红色、味道差且价格中等的苹果, 红色的苹果,味道好,价格低。

我想将这些水果与它们的所有可能的属性组合进行分组,找到相似的,计算并删除重复项。

预期结果

Fruits = [
 {name:apple, color:red,   taste:good,  price:medium, count:2},
 {name:apple, color:red,   taste:bad,   price:medium, count:2},
 {name:apple, color:red,   taste:good,  price:low, count:1},
 {name:apple, color:green, taste:badd,  price:medium, count:2},
];

【问题讨论】:

  • 预期输出是什么?
  • 对它们进行排序。这会将所有重复项放在一个块中,因此您可以在第二遍中轻松计算它们。
  • 这个问题似乎跑题了,因为这不是代码编写服务。
  • @jonrsharpe,是的,我知道,我不会问我要解决的每一个问题,只问那些我无法解决的问题
  • @NestedWeb 那么您尝试的解决方案在哪里,它到底有什么问题?

标签: javascript python algorithm grouping


【解决方案1】:

解决这个问题基本上有两种方法:

  1. O(nlogn) time 最坏的情况,空间很小:对元素进行排序, 然后迭代和计数,相同的元素是相邻的 其他,所以计数相当容易。
  2. O(n) 时间(平均情况)和空间:构建一个哈希映射,其中键是苹果的描述,值是它的出现次数,迭代列表并为每个元素更新哈希映射。

注意它不能做得更好,即O(n)时间和次线性空间,因为这是element distinctness problem的一个特例,不能在线性时间和次线性空间中解决。

【讨论】:

    【解决方案2】:

    在 Python 中,可以这样完成

    from collections import defaultdict
    from operator import itemgetter
    keys = ["name", "color", "taste", "price"]
    d, get_keys = defaultdict(int), itemgetter(*keys)
    
    # Group the items based on their name, color, taste and price and count them
    for item in Fruits:
        d[get_keys(item)] += 1
    
    # Unwrap the groups along with their count    
    result = []
    for key in d:
        temp = dict(zip(keys, key))
        temp["count"] = d[key]
        result.append(temp)
    
    print result
    

    输出

    [{'color': 'green',
      'count': 1,
      'name': 'apple',
      'price': 'medium',
      'taste': 'good'},
     {'color': 'red',
      'count': 2,
      'name': 'apple',
      'price': 'medium',
      'taste': 'good'},
     {'color': 'red',
      'count': 1,
      'name': 'apple',
      'price': 'low',
      'taste': 'good'},
     {'color': 'green',
      'count': 2,
      'name': 'apple',
      'price': 'medium',
      'taste': 'bad'},
     {'color': 'red',
      'count': 2,
      'name': 'apple',
      'price': 'medium',
      'taste': 'bad'}]
    

    【讨论】:

      【解决方案3】:

      在 Python 中,如果您要计算一些东西,请尝试使用 collections.Counter 类;并查看您的数据,您可以使用 collections.namedtuple 来跟踪字段名称。

      这是我的代码:

      >>> from collections import Counter, namedtuple
      >>> from pprint import pprint as pp
      >>> 
      >>> Fr = namedtuple('Fr', 'name, colour, taste, price')
      >>> Fruits = [Fr(*datum) for datum in [('apple', 'red', 'good', 'medium'),
                        ('apple', 'red', 'bad', 'medium'),
                        ('apple', 'red', 'good', 'low'),
                        ('apple', 'red', 'bad', 'medium'),
                        ('apple', 'red', 'good', 'medium'),
                        ('apple', 'green', 'bad', 'medium'),
                        ('apple', 'green', 'bad', 'medium')]]
      >>> pp(Fruits)
      [Fr(name='apple', colour='red', taste='good', price='medium'),
       Fr(name='apple', colour='red', taste='bad', price='medium'),
       Fr(name='apple', colour='red', taste='good', price='low'),
       Fr(name='apple', colour='red', taste='bad', price='medium'),
       Fr(name='apple', colour='red', taste='good', price='medium'),
       Fr(name='apple', colour='green', taste='bad', price='medium'),
       Fr(name='apple', colour='green', taste='bad', price='medium')]
      >>> counted = Counter(Fruits)
      >>> pp(dict(counted))
      {Fr(name='apple', colour='green', taste='bad', price='medium'): 2,
       Fr(name='apple', colour='red', taste='bad', price='medium'): 2,
       Fr(name='apple', colour='red', taste='good', price='low'): 1,
       Fr(name='apple', colour='red', taste='good', price='medium'): 2}
      >>> pp(counted.most_common())
      [(Fr(name='apple', colour='red', taste='good', price='medium'), 2),
       (Fr(name='apple', colour='green', taste='bad', price='medium'), 2),
       (Fr(name='apple', colour='red', taste='bad', price='medium'), 2),
       (Fr(name='apple', colour='red', taste='good', price='low'), 1)]
      >>> 
      

      【讨论】:

        猜你喜欢
        • 2016-01-08
        • 1970-01-01
        • 2013-08-29
        • 2012-10-28
        • 2012-04-26
        • 1970-01-01
        • 1970-01-01
        • 2014-11-10
        • 2011-07-06
        相关资源
        最近更新 更多