列表中每个字符串的最少三个字符的最短唯一组合

时间:2018-11-25 16:21:15

标签: python combinatorics

我想为字符串列表中的每个元素找到最短的唯一字符组合。每个组合至少应由字符串的第一个字符和两个最稀有字符组成(如有必要,还可以包括更多),并且顺序重要。如果一个字符在一个字符串中出现多次,则应该增加权重。

考虑以下示例:

liste = ["apple", "pear", "banana", "xylophone", "bear", "banunu"]
combinations = ["apl", "per", "ban", "xyh", "ber", "bnu"

对于applepe总共出现4次,但是由于papple中出现两次,因此应结合使用

用python编写此逻辑的最有效方法是什么?

1 个答案:

答案 0 :(得分:3)

您可以执行以下操作:

import heapq

from collections import Counter
from operator import itemgetter


def combination(word, n, counts):
    word_count = Counter(word)
    elements = []
    seen = set()
    for i, c in enumerate(word[1:]):
        if c not in seen:
            elements.append((-1 * counts[c], word_count[c], i, c))
            seen.add(c)
    top = heapq.nlargest(n, elements)
    characters = map(itemgetter(3), top)

    return word[0] + ''.join(sorted(characters, key=lambda x: word.index(x)))


lst = ["apple", "pear", "banana", "xylophone", "bear", "banunu"]

counts = Counter(''.join(lst))

result = [combination(w, 2, counts) for w in lst]
print(result)

输出

['apl', 'per', 'ban', 'xyh', 'ber', 'bnu']

这个想法是创建代表每个 unique 字母的优先级标准的元组。因此elements是一个包含元组预置的列表:

  1. counts[c]:总计数(因为您希望最稀有的数字乘以-1)
  2. word_count[c]:单词中字母的具体计数
  3. i:代表字母的第一个位置
  4. c:字母本身。

使用以下方法创建列表elements

elements = []
seen = set()
for i, c in enumerate(word[1:]):
    if c not in seen:
        elements.append((-1 * counts[c], word_count[c], i, c))
        seen.add(c)

请注意,由于字符必须唯一,因此我们使用一组(seen)来保证唯一性。最后,您根据上述条件使用heapq.nlargest来获取顶部的n元素。