【问题标题】:Python list comprehension: return value matching multiple if statements, else return other valuePython列表理解:返回值匹配多个if语句,否则返回其他值
【发布时间】:2017-03-10 21:32:28
【问题描述】:

我正在研究 Python 中的列表理解,并且难以将我的代码压缩为单个列表理解语句。

我正在编写一个函数来搜索如下所示的电影词典列表:

    movies = [
    {
    "name": "Usual Suspects", 
    "imdb": 7.0,
    "category": "Thriller"
    },
    {
    "name": "Hitman",
    "imdb": 6.3,
    "category": "Action"
    },
    {
    "name": "Dark Knight",
    "imdb": 9.0,
    "category": "Adventure"
    }
    ]

我正在尝试编写一个函数,该函数接受电影名称的输入,检查 imdb 分数,如果分数 > 5.5 则返回 True,但如果分数不符合此条件则返回 false。

用传统代码编写,我是这样完成的:

    def good_movie(movie_name):
        for m in movies:        #for each item in movies...
            if m["name"] == movie_name:       #see if movie_name == "name", if it does...
                if m["imdb"] > 5.5:      # See if the movie's score is greater than 5.5...
                    return "True"      # If it is, return "true"
                else:        #otherwise
                    return "False"       #return false

我已经能够在列表理解中编写此代码以返回 true,但如果我还想在电影不符合正确评分标准时返回 false,则无法使函数正常工作。

有效的简短版本是:

    def good_movie(movie_name):
        return ["True" for m in movies if m["name"] == movie_name if m["imdb"] > 5.5]

但是,如果 movie_name 不满足此处列出的两个 if 语句,我希望能够返回 False 值。我已经尝试了几种不同的方法,但无法弄清楚如何使其工作。

这样的东西不起作用:

    def good_movie(movie_name):
        return ["True" if m["imdb"] > 5.5 and if m["name"] == movie_name else "False" for m in movies]

我认为在 if 语句之间添加“and”可能会有所帮助(否则,它会将 if 语句视为独立的,而不是连接的)。

我已经来回处理这个问题很多次了,但是任何人都可以提供的任何帮助都将帮助我更好地理解这些类型的列表推导在未来是如何工作的。

感谢您的帮助!

编辑:感谢大家的回复。这是我关于堆栈溢出的第一篇文章,我已经被我的小请求所获得的响应量所震撼。我知道列表理解不是在实际应用程序中解决这个问题的最佳方法,我只是在学习列表理解的过程中,想看看如何在普通 python 中解决这个问题,而不导入熊猫,等等。再次感谢所有贡献的人!

【问题讨论】:

  • 你为什么使用"True""False"字符串而不是Python的TrueFalse布尔值?
  • 这不是列表理解的情况。列表推导式不仅仅是编写循环的一种时髦方式;它们用于构建列表,您不想在此处的任何地方构建列表。
  • @user2357112 确实如此,但生成器表达式相似,它们用于循环。

标签: python list function if-statement


【解决方案1】:

你在正确的轨道上。这只是使用了几个快捷方式。我认为next 可能是获得满足条件的迭代的第一个元素的最佳方式。

target_movie = "Hitman"

def good(movies, target_movie):
    return next(movie["imdb"] > 5.5 for movie in movies if movie["name"] == target_movie)

good(movies, target_movie)

【讨论】:

  • 感谢您的回复。诚然,我对 python 和一般编程是全新的,所以我仍然熟悉 python 可用的各种方法。我对您编写的解决方案的理解是,下一个方法是遍历电影列表中的每个项目,并在确定电影 ["name "] == 目标电影。如果它找不到匹配 target_movie 的电影名称,它也返回 false。这或多或少是正确的吗?
  • 别在意最后一点,如果在电影列表中找不到 target_movie,该函数似乎会导致错误。这是一个需要解决的单独问题,但您帮助我突破了我试图解决的问题。再次感谢!
  • 不用担心。为了进一步了解我的解决方案,我建议在生成器表达式上运行list 而不是next,即list(movie["imdb"] > 5.5 for movie in movies if movie["name"] == target_movie)next 只是获取 this 的第一个元素而不是所有元素。您的描述看起来基本正确,除非movie["name"] == target_movie 不满意,否则根本不会将任何内容添加到列表中(不是False)。阅读 Python 理解以了解更多信息。
【解决方案2】:
index = next(index for (index, d) in enumerate(lst) if d["name"] == movie_name)

结合基于索引的分数查找,你很好!

【讨论】:

    【解决方案3】:

    如果您计划对分数进行多次评估,那么您应该重新考虑您的数据结构。如果您只遍历该字典列表一次,那么这样做可能没问题,但您最终想要评估不止一部电影。如果你不止一次为同一个电影列表调用评估,这比每次循环遍历列表更有效:

    scores = {d['name']: d['imdb'] for d in movies}
    
    def evaluate(name):
        return scores[name] > 5.5
    

    它首先使用 dictcomp 构建名称到分数的映射,然后函数是微不足道的。

    【讨论】:

      【解决方案4】:

      我知道您想循环遍历列表,但也许您可以考虑其他方式。在您的情况下,Pandas 会更容易使用。

          import pandas as pd
      
          movies = [
           {
           "name": "Usual Suspects", 
           "imdb": 7.0,
           "category": "Thriller"
           },
           {
           "name": "Hitman",
           "imdb": 6.3,
           "category": "Action"
           },
           {
           "name": "Dark Knight",
           "imdb": 9.0,
           "category": "Adventure"
           }
           ]
      
           movie_pd = pd.DataFrame(movies)
           # find movies that have more than 7.5 scores in imbd.
           movie_pd['good_movie'] = movie_pd[ movie_pd['imdb'] > 7.5].name
      

      输出:

        In[6]:movie_pd
        Out[6]: 
              category  imdb            name   good_movie
          0   Thriller   7.0  Usual Suspects          NaN
          1     Action   6.3          Hitman          NaN
          2  Adventure   9.0     Dark Knight  Dark Knight
      

      【讨论】:

        猜你喜欢
        • 2017-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多