列表中的最长字符串超过1个?

时间:2018-09-10 19:18:26

标签: python python-3.x

我有所有美国州名的列表。

states = ['Oklahoma', 'Kansas', 'North Carolina', 'Georgia', 'Oregon',
      'Mississippi', 'Minnesota', 'Colorado', 'Alabama',
      'Massachusetts', 'Arizona', 'Connecticut', 'Montana',
      'West Virginia', 'Nebraska', 'New York', 'Nevada', 'Idaho',
      'New Jersey', 'Missouri', 'South Carolina', 'Pennsylvania',
      'Rhode Island', 'New Mexico', 'Alaska', 'New Hampshire',
      'Tennessee', 'Washington', 'Indiana', 'Hawaii', 'Kentucky',
      'Virginia', 'Ohio', 'Wisconsin', 'Maryland', 'Florida',
      'Utah', 'Maine', 'California', 'Vermont', 'Arkansas', 'Wyoming',
      'Louisiana', 'North Dakota', 'South Dakota', 'Texas',
      'Illinois', 'Iowa', 'Michigan', 'Delaware']

我想在此项目列表中找到最长的字符串,使用以下命令很容易做到:

def longest_state(data):
    return(max(states,key=len))
print(longest_state(states)

这将返回长度为14的“北卡罗莱纳州”。但是,“南卡罗来纳州”也是14,但不会返回。

我尝试使用以下stackoverflow线程,该线程具有使用列表推导查找多个最长字符串的示例,但我无法使其工作... Python's most efficient way to choose longest string in list?

我还尝试使用if / else语句将列表项附加到另一个变量,如果该列表项等于当前最长项的长度,但不成功

有人可以帮忙吗?

7 个答案:

答案 0 :(得分:3)

您可以将所有最长的名称存储在一个数组中

def longest_state(data):
    cur_longest = []
    cur_longest_num = 0
    for state in data:
        if len(state) == cur_longest_num:
            cur_longest.append(state)
        elif len(state) > cur_longest_num:
            cur_longest = [state]
            cur_longest_num = len(state)
    return cur_longest

答案 1 :(得分:2)

希望这会有所帮助。 两遍方法,可能不是最好的。但是肯定是O(n)。

def longest_state(states):
    max_len = len(max(states, key=len))
    return [state for state in states if len(state) == max_len]

最好通过1次,但这看起来更短。

答案 2 :(得分:1)

s = len(max(states, key=len))
[i for i in states if len(i) == s]

答案 3 :(得分:1)

根据长度输入字典:

>>> from collections import defaultdict
>>> len2states = defaultdict(list)
>>> for state in states:
...     len2states[len(state)].append(state)
...     
>>> len2states[max(len2states)]
['North Carolina', 'South Carolina']

答案 4 :(得分:1)

这个问题让我想知道所有可能的解决方案中哪一个具有最佳性能,因此我比较了我想到的所有尚未发布的解决方案,并将它们与我的进行了比较。

groupby方法:

sorted_states = sorted(states, key=len, reverse=True)
grouped_states = next(groupby(sorted_states, key=len))
list(grouped_states[1])

groupby需要一个排序的列表才能正常工作,因此事先需要对列表进行排序的“开销”,但是大多数Python解释器都对排序算法进行了优化。我们用next在第一个组出现时停止生成器,因此它不会继续获取其余项。

takewhile方法:

sorted_states = sorted(states, key=len, reverse=True)
max_length = len(sorted_states[0])
list(takewhile(lambda x: max_length == len(x), sorted_states))

这也需要一个排序的列表,以及第一项的长度,但是一旦不再满足lambda的期望,它就会停止收集新列表。

reduce方法:

def _keep_longest(a, v):
  if len(a) == 0 or len(v) >= len(a[-1]):
    a.append(v)
  return a

sorted_states = sorted(states, key=len, reverse=True)
reduce(_keep_longest, sorted_states, [])

这需要一种方法来处理先前长度和排序列表之间的比较。它的所有长度比较以及从lambda到lambda的移动列表都使该方法无效。

此问题的其他答案

我包括了其他答案(来自各种海报的maxlen,以及@Spencer Bard,@ Wim和其他列表推导式在每次比较的最大扫描次数上达到了len)测试以及比较它们的性能

结果

当然结果有很大的不同,但是一遍又一遍地重复(在repl.it上样本大小为50_000),我可以说它们具有代表性(让它们在我的cPython 3.5上也运行几次):

max and len 50_000 times: 1.3888958770003228
sort and groupby 50_000 times: 1.405984859000455
sort and takewhile 50_000 times: 1.4154430249991492
spencer 50_000 times: 1.607105290000618
wim 50_000 times: 1.9011182049998752
sort and reduce 50_000 times: 4.612968634999561
comprehension 50_000 times: 27.802522705999763

结论

在这里多次发布的maxlen方法很可取,这可能是最Python的方式,因为它是不言自明的,无需借助列表排序或{{1 }},itertoolsfunctools库。

Online demo here

答案 5 :(得分:0)

longest_state = max(states, key=len)

for i in states:
    if len(i) == len(longest_state):
        print(i)

备用格式

longest_state = max(states, key=len)

[[print(i)] for i in states if len(i) == len(longest_state)]

答案 6 :(得分:-1)

另一种可能的解决方案。很矮很甜

def longest_state(data):
    return [state for state in data if len(state) == len(max(data, key=len))]