【问题标题】:Iterate over two strings and count repeated letters遍历两个字符串并计算重复的字母
【发布时间】:2017-10-01 14:10:01
【问题描述】:

我通过命令行接受两个字符串。

我想要的是,

  • 如果第一个字符串包含的 z 比第二个字符串多,则第一个字符串获胜。
  • 如果他们有相同的号码 z 的,然后 y 最多的字符串获胜。

  • 如果它们的 y 数量相同,则 x 的数量 确定获胜者等。

  • 如果它们包含相同数量的z,y .... a,则为平局 而且没有赢家。

我本来打算做的是,

创建一个包含所有字母的字典并分配递增值,例如,

alphabets = dict(a=1, b=2, c=3, ... ,y=25, z=26)

并将其值乘以字母重复的次数。

For example, python myprogram.py zzza zzza 
string1: zzza and string2: zzza 
In string1, Z is repeated 3 times and a is repeated once.
In string2, Z is repeated 2 times, b and a is repeated once.
So, (26*3) + (2*1) and (26*2) + (2*1) + (1*1)

具有最大数量的字符串将获胜。但是,它并不总是给出正确的答案。 (string1: zzza and string2: zyyx 条件失败)

word1_count = {}
word2_count = {}

class FindWinner:
def __init__(self, word1, word2):
    self.word1 = word1
    self.word2 = word2

def check_conditions(self):

    special_chars = set('[~!@#$%^&*.-()_+{}":;01234567989\']+$')

# check conditions 
    if special_chars.intersection(self.word1) or 
         special_chars.intersection(self.word2) or \
        (len(self.word1) != len(self.word2) or ('no' in self.word1)
        or ('no' in self.word2)) or (self.word1 == self.word2):

       print('Invalid string.')

    else:
        print("String is valid")

        for w1 in list(self.word1):
            if w1 not in word1_count:
                word1_count[w1] = 1
            else:
                word1_count[w1] += 1

        for w2 in list(self.word2):
                if w2 not in word2_count:
                    word2_count[w2] = 1
                else:
                    word2_count[w2] += 1

        # print(word1_count, word2_count)

    merged_data = [[k, word1_count.get(k, 0), word2_count.get(k, 0)] for k in word1_count.keys() | word2_count.keys()]

    print(merged_data)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("word1", help="First word")
    parser.add_argument("word2", help="Second word")
    args = parser.parse_args()

    c1 = FindWinner(args.word1, args.word2)
    c1.check_conditions()


if __name__ == "__main__":
    main()

输入: python myprogramm.py qwwweq asdnnn

输出:

String is valid {'e': 1, 'q': 2, 'w': 3} {'d': 1, 'a': 1, 'n': 3, 's': 1} # merged_data

应该采用什么方法? 谢谢

【问题讨论】:

  • 嘿@batMan,我不确定你在说什么。

标签: string python-3.x dictionary


【解决方案1】:

您的方法不起作用,因为 26 个 a 字符的分数与 1 个 z 字符的分数相同; 26 * 1 == 1 * 26。

您应该将其视为排序问题,您是按字母数排序的。计算每个单词中的字母,然后按字母倒序将计数作为一个元组,让 Python 用max() 选出获胜者。 Python 序列按字典顺序进行比较; [3, 2] 的列表在 [3, 1] 之后排序,因为第二个数字比第一个大; max() 会选择它。

使用collections.Counter() object 可以轻松完成计数:

from collections import Counter
from string import ascii_lowercase

def letter_counts(word):
    counts = Counter(word)
    return [counts.get(l, 0) for l in reversed(ascii_lowercase)]

lcounts1 = letter_counts(word1)
lcounts2 = letter_counts(word2)
if lcounts1 == lcounts2:
    # tie
    print('No winner')
else:
    _, winner = max((lcounts1, word1), (lcounts2, word2))
    print(winner)

letter_counts() 生成一个由 26 个整数组成的列表,每个整数都是字母 za 的计数。

【讨论】:

    【解决方案2】:

    这可以在没有字典的情况下完成。
    创建字典作为预处理的一部分是额外的开销。
    我们可以在两个字符串中一个一个地检查从(z..a) 开始的每个字母的计数。如果有最大值,我们可以打破循环并宣布获胜者。这比使用字典解决这个问题要有效得多。

    from string import ascii_lowercase
    
    str1="hellozzzz"
    str2="yellozzzz"
    winner=""
    
    for ele in reversed(ascii_lowercase):
        diff=str1.count(ele)-str2.count(ele)
        if(diff>0):
            winner=str1
            break
        elif (diff<0):
            winner=str2
            break
    
    print winner if(winner) else "It's a tie"
    

    【讨论】:

    • 谢谢蝙蝠侠。我检查了各种字符串,但在少数情况下程序失败了。输入:str1="yellozzzzzz" str2="hellozzzzzz" 输出:hellozzzzzz 是赢家 根据条件,yellozzzzzz 应该是赢家
    • 对不起!!一个失误。如果您签入我正在为 str1 设置字典的第一个 for 循环,我在其他情况下提到了 d[l]=0。我已经纠正了它做 d[l]=1,更新了答案,它工作正常。
    • 这与我的回答完全相同,只是没有 Counter 对象和max()
    • 我会说this is more efficient,因为它不会对所有字母和stops 进行预处理,只要满足条件,就无需检查和存储更多字母的计数:)
    • @batman:不,计数已经完成,并且是 O(K),其中 K 是输入的长度。仅将计数整理到列表中是短路的。最多查找 26 个这样的数字,因此几乎没有机会使其更快。在我的答案中进行比较的 C 代码可能仍然会胜过一个字符串比另一个字符串具有更多 z 字符的字符串的比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 2016-01-01
    • 2023-03-25
    • 2016-05-17
    相关资源
    最近更新 更多