Python 确定“字符串”是否为等值线

Python 确定“字符串”是否为等值线,python,pattern-matching,Python,Pattern Matching,要确定字符串是否为等值线,请执行以下操作: 确定一个单词或短语是否为等值线。等值线(也称为 “非模式词”)是没有重复字母的词或短语, 但是,空格和连字符可以多次出现 我的尝试: def is_isogram(string): word = string.lower() if word == "": return False elif word == " ": return False else: for char

要确定字符串是否为等值线,请执行以下操作:

确定一个单词或短语是否为等值线。等值线(也称为 “非模式词”)是没有重复字母的词或短语, 但是,空格和连字符可以多次出现

我的尝试:

def is_isogram(string):
    word = string.lower()

    if word == "":
        return False
    elif word == " ":
        return False
    else:
        for char in word:
            if (word.count(char) > 1) and (char != " " or char != "-") and (len(word) > 0):
                return False
            else:
                return True
但是,当传递给函数的字符串为空且两个中心字符相同时,此操作失败

以下是单元测试:

import unittest
from isogram import is_isogram

class IsogramTest(unittest.TestCase):

    def test_empty_string(self):
        self.assertIs(is_isogram(""), True)

    def test_isogram_with_only_lower_case_characters(self):
        self.assertIs(is_isogram("isogram"), True)

    def test_word_with_one_duplicated_character(self):
        self.assertIs(is_isogram("eleven"), False)

    def test_word_with_one_duplicated_character_from_end_of_alphabet(self):
        self.assertIs(is_isogram("zzyzx"), False)

    def test_longest_reported_english_isogram(self):
        self.assertIs(is_isogram("subdermatoglyphic"), True)

    def test_word_with_duplicated_character_in_mixed_case(self):
        self.assertIs(is_isogram("Alphabet"), False)

    def test_hypothetical_isogrammic_word_with_hyphen(self):
        self.assertIs(is_isogram("thumbscrew-japingly"), True)

    def test_isogram_with_duplicated_hyphen(self):
        self.assertIs(is_isogram("six-year-old"), True)

    def test_made_up_name_that_is_an_isogram(self):
        self.assertIs(is_isogram("Emily Jung Schwartzkopf"), True)

    def test_duplicated_character_in_the_middle(self):
        self.assertIs(is_isogram("accentor"), False)

    # Additional tests for this track

    def test_isogram_with_duplicated_letter_and_nonletter_character(self):
        self.assertIs(is_isogram("Aleph Bot Chap"), False)


if __name__ == '__main__':
    unittest.main()

在满足这两个测试用例时,我做错了什么?

使用
集合要简单得多。计数器
字符串。ascii_小写
只检查字母字符:

from collections import Counter
from string import ascii_lowercase

def is_isogram(s:str) -> bool:
  c = Counter(s.lower())
  return all(c[i] < 2 for i in ascii_lowercase)

tests = [('', True), ('isogram', True), ('eleven', False), ('zzyzx', False), ('subdermatoglyphic', True), ('Alphabet', False), ('thumbscrew-japingly', True), ('six-year-old', True), ('Emily Jung Schwartzkopf', True), ('accentor', False), ('Aleph Bot Chap', False)]
for a, b in tests:
  assert is_isogram(a) == b

print('all tests passed')

使用
collections.Counter
string.ascii_lowercase
只检查字母字符要简单得多:

from collections import Counter
from string import ascii_lowercase

def is_isogram(s:str) -> bool:
  c = Counter(s.lower())
  return all(c[i] < 2 for i in ascii_lowercase)

tests = [('', True), ('isogram', True), ('eleven', False), ('zzyzx', False), ('subdermatoglyphic', True), ('Alphabet', False), ('thumbscrew-japingly', True), ('six-year-old', True), ('Emily Jung Schwartzkopf', True), ('accentor', False), ('Aleph Bot Chap', False)]
for a, b in tests:
  assert is_isogram(a) == b

print('all tests passed')

您可以使用
re.sub
删除允许重复的字符,然后比较
list(您的\u字符串)
set(您的\u字符串)
的长度

至于你错在哪里:
如果word==”:则显式地说
:返回False
,然后说
self.assertIs(is_isogram(“”,True)
,因此我认为这是一个简单的错误,您可以用一种或另一种方法修复。
只要第一个字符不重复,它就会失败,因为如果第一个字符不重复,则word中字符的
循环将返回
True
。检查完所有字符后,您可能希望
返回True

您可以使用
re.sub
删除允许重复的字符,然后比较
列表(您的\u字符串)
设置(您的\u字符串)
的长度

至于你错在哪里:
如果word==”:则显式地说
:返回False
,然后说
self.assertIs(is_isogram(“”,True)
,因此我认为这是一个简单的错误,您可以用一种或另一种方法修复。
只要第一个字符不重复,它就会失败,因为如果第一个字符不重复,则word中字符的
循环将返回
True
。检查完所有字符后,您可能希望您的
返回True

您的错误位于:

(一)

及(二)

及(三)

(1) :您的测试表明空字符串是等值线,因此此
if
应返回
True

(2) :这是一个同义反复,因为它总是返回
True
。考虑一下你的<代码> char <代码>是一个空的空间,然后<代码> char!“
将为
False
,但
char!=“-”
将返回
True
True或False
True

(3) :如果字符串的第一个字母没有重复,则返回True,而不分析字符串的其他字母。因此,您应该仅在for循环完成时才放置此返回

因此,修复这些问题后,您的代码将运行良好:

def is_isogram(string):
    word = string.lower()

    if word == "":
        return True
    elif word == " ":
        return False
    else:
        for char in word:
            if word and char not in ' -' and word.count(char) > 1:
                return False
        return True
以及您的测试结果:

...........
----------------------------------------------------------------------
Ran 11 tests in 0.000s

OK

PS:您也可以按照@Ajax1234和@MoxieBall的建议将此代码重写为更简单的代码

或者你可以这样做:

def is_isogram(word):
    filtered_word = filter(lambda x: x not in ' -', word.lower())
    return len(filtered_word) == len(set(filtered_word))

那么,您的错误是:

(一)

及(二)

及(三)

(1) :您的测试表明空字符串是等值线,因此此
if
应返回
True

(2) :这是一个同义反复,因为它总是返回
True
。考虑一下你的<代码> char <代码>是一个空的空间,然后<代码> char!“
将为
False
,但
char!=“-”
将返回
True
True或False
True

(3) :如果字符串的第一个字母没有重复,则返回True,而不分析字符串的其他字母。因此,您应该仅在for循环完成时才放置此返回

因此,修复这些问题后,您的代码将运行良好:

def is_isogram(string):
    word = string.lower()

    if word == "":
        return True
    elif word == " ":
        return False
    else:
        for char in word:
            if word and char not in ' -' and word.count(char) > 1:
                return False
        return True
以及您的测试结果:

...........
----------------------------------------------------------------------
Ran 11 tests in 0.000s

OK

PS:您也可以按照@Ajax1234和@MoxieBall的建议将此代码重写为更简单的代码

或者你可以这样做:

def is_isogram(word):
    filtered_word = filter(lambda x: x not in ' -', word.lower())
    return len(filtered_word) == len(set(filtered_word))

你能解释一下你的代码吗?@Artemis问题的关键在于字母字符只能出现一次。因此,可以找到输入中所有字符的频率(使用
collections.Counter
),然后进行简单检查以确定所有字母字符的计数小于2,产生期望的结果。你能评论一下你的代码来解释发生了什么吗?@Artemis问题的重要因素是字母字符只能出现一次。因此,可以找到输入中所有字符的频率(使用
collections.Counter
),然后进行简单检查以确定所有字母字符的计数小于2,产生所需的结果。您可以将
if
条件整理为
word和char不在“-”和word中。count(char)>1
谢谢您的反馈,@MoxieBall。编辑!如果
if
条件为
word和char不在“-”和word.count(char)>1,您可以整理该
,谢谢您的反馈,@MoxieBall。编辑!
def is_isogram(word):
    filtered_word = filter(lambda x: x not in ' -', word.lower())
    return len(filtered_word) == len(set(filtered_word))