【问题标题】:Remove an item in one set that has an item containing the other sets item删除一个集合中的一个项目,该项目具有包含其他集合项目的项目
【发布时间】:2019-07-12 08:23:03
【问题描述】:

我的整个应用程序有点sitemap-Scraper,我将根链接提供给它,从这里它会扫描站点以获取更多链接,然后也抓取这些站点以获取更多链接,有点像站点地图生成,只是更详细. 大局是,有些网站包含 youtube、facebook、google 等。这些网站可能会导致进一步的永恒,并将我的应用程序置于一个边缘链中,因此我决定为它提供一个拦截器,以便我们可以删除那些更大的网站

我有一个名为 blocked_sites.txt 的文件,其中有:

facebook
youtube

我有一个set,其中有:

'facebook.com', 'youtube.com', 'gold'

所以,我想做的是:

  1. 比较两个列表
  2. 检查是否 urls-item CONTAINS blocked_sites item
  3. 如果该项目包含 BLOCKED 项目,则删除该项目

第 1&2 点我搞定了,但第三点是个陷阱,这是我先发制人的尝试:

 # For every url in urls
 for url in urls:
   # For every blocker inside blocked
   for blocker in blocked:      
      # If URL contains BLOCKER
      if blocker in url:
         # Remove THAT URL
         urls.remove(url)
         print('removed: ' + url)
print(urls)

问题是我不能真正修改一个集合,同时迭代它。那么我有什么选择呢?

这是我的想法:

  1. DOESNT包含拦截器的URL复制到另一组 --这似乎有点笨重,我的意思是,我们将不得不处理 urls、blocker、new_urls 并且似乎不是一个好主意,特别是如果我不断地喂更多还有更多指向旧列表的链接,似乎不是很节省内存
  2. 让我们尝试将它们转换为列表! - 嘿!有效!像只有 3 件? --进一步看,set already is a list? 然而,当我使用 { 'item' } 而不是 [ 'item' ] 作为我的设置时,我得到了一个错误?

好的,先拿这些:

urls = {'facebook.com', 'youtube.com', 'gold'}
blocked = {'facebook'}
>> Set changed during iteration

好吧,就这样吧:

urls = ['facebook.com', 'youtube.com', 'gold']
blocked = ['facebook']
>>> Removed: facebook

是的,它成功了!

如果我们像这样添加更多的拦截器会怎样:

urls = ['facebook.com', 'youtube.com', 'gold']
blocked = ['facebook', 'youtube']
>>>Removed: facebook
   ['youtube.com', 'gold']

这很奇怪!由于某种原因,它只能脱掉一个阻挡器?

我如何获得金币

【问题讨论】:

  • for url in list(urls):

标签: python


【解决方案1】:

在迭代期间更改列表/集合的内容通常会导致灾难。在几乎所有情况下,最好构造一个新的列表/集合而不是就地操作。理解起来很简单:

urls = ['facebook.com', 'youtube.com', 'gold']
blocked = ['facebook', 'youtube']

urls = [url for url in urls if not any(blocker in url for blocker in blocked)]
print(urls)
# ['gold']

有套装:

urls = {'facebook.com', 'youtube.com', 'gold'}
blocked = {'facebook', 'youtube'}

urls = {url for url in urls if not any(blocker in url for blocker in blocked)}
print(urls)
# {'gold'}

但是,请注意,遍历集合非常慢,而列表选项可能更快。

【讨论】:

    【解决方案2】:

    我们可以进一步扩展您的方法,以仅使用集合操作来实现您想要的。

    found = set()
    urls = {'facebook.com', 'youtube.com', 'gold'}
    blocked = {'facebook', 'youtube'}
    
    for url in urls:
        for blocker in blocked:
            if blocker in url:
                found.add(url)
    
    urls.difference(found)
    
    {'gold'}
    

    【讨论】:

      猜你喜欢
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      • 1970-01-01
      • 2013-07-13
      • 2013-05-15
      • 1970-01-01
      相关资源
      最近更新 更多