Python:合并子列表;跨越多行

Python: Consolidating sublists; spanning multiple lines

我有一个看起来像这样的列表:

[u'https://www.microsoft.com']
[u'https://www.microsoft.com']
[u'https://products.office.com/en-us/home']
[u'https://www.microsoft.com/en-us/windows/']
[u'https://www.microsoft.com/surface/en-us']
[u'https://www.xbox.com/en-us']

我想稍微清理一下输出、对值进行排序、删除重复条目等。但在当前格式中,它不是将每个值作为一个完整的单独元素进行操作,而是对单个字符进行操作(即只是一串单独的字母)。我得到的只是无意义的文本字符串。

所以基本上,我想将所有子列表合并到一个列表中,在一行中,采用以下(常规)格式:

['https://www.microsoft.com', 'https://www.microsoft.com', 'https://products.office.com/en-us/home', 'https://www.microsoft.com/en-us/windows/', 'https://www.microsoft.com/surface/en-us', 'https://www.xbox.com/en-us']

我是 Python 的新手,所以我有可能错过了一些东西(或者在某些时候使用了不正确的术语),但这(以及方括号的位置)是我假设的原因这被认为是一个列表(and/or 多个子列表);如果我用 print(type(links)) 替换 print(links),我会得到以下输出:

<type 'list'>
<type 'list'>
<type 'list'>
<type 'list'>
<type 'list'>
<type 'list'>

定义 links 的原始代码看起来像这样:

class LinkParser(HTMLParser):
  def handle_starttag(self, tag, attrs):
    links = []
    if tag == 'a':
      for attr in attrs:
        if attr[0] == 'href':
          links.append(attr[1])
          print(links)

看起来您在 my_list 中有一个列表列表。如果是

l = [['https://www.microsoft.com'],
['https://www.microsoft.com'],
['https://products.office.com/en-us/home'],
['https://www.microsoft.com/en-us/windows/'],
['https://www.microsoft.com/surface/en-us'],
['https://www.xbox.com/en-us']]

res = []
for i in l:
    if i[0] not in res:
        res.append(i[0])
print(res)

输出:

['https://www.microsoft.com', 'https://products.office.com/en-us/home', 'https://www.microsoft.com/en-us/windows/', 'https://www.microsoft.com/surface/en-us', 'https://www.xbox.com/en-us']

toolz.concat 对于这种任务来说非常高效(作为惰性函数)和优雅。

from toolz import concat

lst = [['https://www.microsoft.com'],
['https://www.microsoft.com'],
['https://products.office.com/en-us/home'],
['https://www.microsoft.com/en-us/windows/'],
['https://www.microsoft.com/surface/en-us'],
['https://www.xbox.com/en-us']]

list(concat(lst))  # for a sorted list, replace list with sorted

# ['https://www.microsoft.com',
#  'https://www.microsoft.com',
#  'https://products.office.com/en-us/home',
#  'https://www.microsoft.com/en-us/windows/',
#  'https://www.microsoft.com/surface/en-us',
#  'https://www.xbox.com/en-us']

或者,如果你想要一套:

set(concat(lst))

# {'https://products.office.com/en-us/home',
#  'https://www.microsoft.com',
#  'https://www.microsoft.com/en-us/windows/',
#  'https://www.microsoft.com/surface/en-us',
#  'https://www.xbox.com/en-us'}

如果您没有toolz,您可以使用下面的代替。 toolz 通常可以轻松访问隐藏在其他库中的一些常见的难以找到的函数。

import itertools
itertools.chain.from_iterable(...)
data = [['https://www.microsoft.com'],
['https://www.microsoft.com'],
['https://products.office.com/en-us/home'],
['https://www.microsoft.com/en-us/windows/'],
['https://www.microsoft.com/surface/en-us'],
['https://www.xbox.com/en-us']]

from itertools import chain

new_list = list(dict.fromkeys(chain.from_iterable(data)))

print(new_list)
>>>
['https://www.microsoft.com',
 'https://products.office.com/en-us/home',
 'https://www.microsoft.com/en-us/windows/',
 'https://www.microsoft.com/surface/en-us',
 'https://www.xbox.com/en-us']

您没有一个列表,而是 6 个列表和一个元素。如果你想收集 所有这些都变成一个没有重复的项目我建议你使用 set:

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        my_set = set()
        if tag == 'a':
            for attrs in attrs:
                if attrs[0] == 'href' and '.' in attrs[1]:
                    my_set.add(attrs[1])
        print(sorted(my_set))

...我无法测试;你可能需要稍微调整一下。

好的,我明白了:

  1. 问题中的object/list(即links),需要在函数范围外初始化and/or class 在其中定义它(即项目附加到它的代码块)。它可以在之前,也可以在之后;只要它首先被解释。

  2. 同样适用于调用print()语句(关于作用域),但应该最后解释(在调用函数and/or class 设置)。


例如:

输入:

class LinkParser(HTMLParser):
  def handle_starttag(self, tag, attrs):
    if tag == 'a':
      for attr in attrs:
        if attr[0] == 'href':
          links.append(attr[1])

links = []
LinkParser().feed(html)
print(links)

输出:

[u'<a href="https://www.microsoft.com" rel="nofollow noreferrer">https://www.microsoft.com</a>', u'<a href="https://www.microsoft.com" rel="nofollow noreferrer">https://www.microsoft.com</a>', u'<a href="https://products.office.com/en-us/home" rel="nofollow noreferrer">https://products.office.com/en-us/home</a>', u'<a href="https://www.microsoft.com/en-us/windows/" rel="nofollow noreferrer">https://www.microsoft.com/en-us/windows/</a>', u'<a href="https://www.microsoft.com/surface/en-us" rel="nofollow noreferrer">https://www.microsoft.com/surface/en-us</a>', u'<a href="https://www.xbox.com/en-us" rel="nofollow noreferrer">https://www.xbox.com/en-us</a>']</pre>