首页 > 解决方案 > 拆分 JSON python 字符串以传递给函数

问题描述

我如何尝试将我的 JSON 与所有电影拆分并将它们分别发送到 finalScore 函数,然后在最后附加到我的列表中?

抱歉,解释和代码很大,我真的不确定要描述和展示我的问题而不展示我做了什么。

这是我当前的代码:

import datetime, json

def jsonData(data):
    return json.loads(data)

def findContentInformation(content):
    contentData = convert_content_data(content)

    for info in contentData:
        contentBaseScore = info['popularityScore']
        contentBrand = info['brand']
        contentType = info['contentType']
        contentName = info['title']
        contentInformation = [contentBaseScore, contentBrand, contentType, contentName]
        
   
    return contentInformation

#Calculator the overall rating for the film
def getRating(content_data, userBrandRate, userTypeRate):
    
    contentScore = {}

    #RATING
    rating = 0

    # Collecting information from the content to be tested
    contentInfo = findContentInformation(content_data) # The content being tested
    popularityScore += contentInfo[0] #Find base score and add this to popScore

    #getBrandRating = str((userBrandPreference[contentInfo[1]])) # Get brand preference

    # Check if brand preference rating is a valid rating type
    if brandRating in Ratings:
        popularityScore += Ratings[brandRating] # Get the ratings score & update popScore
    else:
        print("Unrecognized rating value found in this search")

    user_content_type_preference = convert_type_preferences(content_type_preferences)
    typeRating = getTypeRating(user_content_type_preference, contentInfo) # Get the type rating

    # Check if type rating is a valid rating
    if typeRating in Ratings:
        popularityScore += Ratings[typeRating] # Update the popScore based on the rating score 
    else:
        print("Unrecognized rating value found in this search")

    contentScore[contentInfo[3]] = popularityScore
    popularityScore = 0

    return contentScore

result = getRating(content_data)

我的输出只有一部电影(不确定如何使用 JSON 中的所有电影)

JSON字符串:

content_data = """[{ "title": "Spider-Man", "brand": "Marvel",
"Rating": 98, "contentIs": "movie" }]"""

输出:

[{'Spider-Man': 128}]

标签: pythonjsonpython-3.x

解决方案


对我来说,感觉就像你让事情变得不必要的复杂。例如,您有三个函数(convert_content_dataconvert_preferencesconvert_type_preferences,它们都做同样的事情——它们都采用一个 JSON 编码的字符串并对其进行解析。将这三个函数合二为一仍然是一个太多的函数,因为我不认为json.loads,作为一个单一的副作用,首先是一个完全独立的函数的良好候选者。

你也做了很多转换——从 JSON 编码的字符串到字典。你这样做多次。为什么不在程序开始时将所有 JSON 转换一次?这样做可以让您使用字典来完成其余任务。一旦有了字典列表,您就可以将每部字典视为一个“电影对象”,因为这就是每部字典所代表的内容。品牌和内容类型的 JSON 字符串也可以在程序开始时转换一次(而不是在整个程序中多次转换)。


编辑 - 我已经更新了我的示例代码。

首先,我认为你应该把你的电影数据放在一个单独的 JSON 文件中,这样你就不会用一个巨大的字符串文字污染你的源代码。让我们命名它movies.json

[
    {
        "title": "Spider-Man",
        "brand": "Marvel",
        "availability": ["CA","FR","US"],
        "availableDate": "2019-11-12T05:00:00.000Z",
        "isKidsContent": true,
        "popularityScore": 98,
        "contentType": "movie"
    },
    
    {
        "title": "Float",
        "brand": "Pixar",
        "availability": ["US"],
        "availableDate": "2019-11-12T05:00:00.000Z",
        "isKidsContent": true,
        "popularityScore": 87,
        "contentType": "short"
    },
    {
        "title": "Avatar",
        "brand": "21st Century Fox",
        "availability": ["US","CA","FR","ES","DE"],
        "availableDate": "2019-11-12T05:00:00.000Z",
        "isKidsContent": false,
        "popularityScore": 99,
        "contentType": "movie"
    },
    
    {
        "title": "Chapter 1: The Mandalorian",
        "brand": "Star Wars", "availability": ["US","CA"],
        "availableDate": "2019-11-02T23:00:00.000Z",
        "isKidsContent": false,
        "popularityScore":  92,
        "contentType": "series"
    },
    
    {
        "title": "Marvel Studios Avengers: Endgame",
        "brand": "Marvel",
        "availability": ["CA","FR","ES","DE","US"],
        "availableDate": "2019-11-11T23:00:00.000Z",
        "isKidsContent": false,
        "popularityScore": 87,
        "contentType": "movie"
    },
    
    {
        "title": "Disney Mickey Mouse Clubhouse: Mickey Goes Fishing",
        "brand": "Disney",
        "availability": ["US"],
        "availableDate": "2019-09-11T22:00:00.000Z",
        "isKidsContent": true,
        "popularityScore": 75,
        "contentType": "series"
    },
    
    {
        "title": "Disney High School Musical: The Musical: The Series: Act Two",
        "brand": "Disney",
        "availability": ["US","FR","ES"],
        "availableDate": "2020-01-10T08:00:00.000Z",
        "isKidsContent": false,
        "popularityScore": 97,
        "contentType": "series"
    }
]

然后,我还将为您的所有用户创建一个 JSON 文件。这是您存储用户首选项的地方。让我们命名它users.json

[

    {
        "name": "Bob",
        "preferences": {
            "brand": {
                "Star Wars": "love",
                "Disney": "like",
                "Marvel": "dislike",
                "Pixar": "dislike"
            },
            "contentType": {
                "movie": "like",
                "series": "like",
                "short": "dislike"
            }
        }
    },
    
    {
        "name": "Joe",
        "preferences": {
            "brand": {
                "Star Wars": "dislike",
                "Disney": "dislike",
                "Marvel": "dislike",
                "Pixar": "dislike"
            },
            "contentType": {
                "movie": "like",
                "series": "like",
                "short": "dislike"
            }
        }
    }
    
]

users.json文件有两个名为Boband的用户Joe,具有不同的偏好。

然后,代码:

def evaluate_score(user, movie):
    """
    Evaluates and returns the score a user would assign to
    a given movie based on the user's brand- and content-type preferences.
    """

    ratings = {
        "dislike": -20,
        "indifferent": 0,
        "like": 10,
        "adore": 30,
        "love": 50
    }

    brand_score = ratings.get(user["preferences"]["brand"].get(movie["brand"])) or 0
    content_type_score = ratings.get(user["preferences"]["contentType"].get(movie["contentType"])) or 0

    return movie["popularityScore"] + brand_score + content_type_score


def get_all_scores(user, movies):

    for movie in movies:
        yield {
            "title": movie["title"],
            "score": evaluate_score(user, movie)
        }
    

def main():

    import json
    from operator import itemgetter

    with open("movies.json", "r") as file:
        movies = json.load(file)

    with open("users.json", "r") as file:
        users = json.load(file)

    for user in users:
        print(user["name"].center(16, "-"))
        for movie in sorted(get_all_scores(user, movies), key=itemgetter("score"), reverse=True):
            print("{}: {}".format(movie["title"], movie["score"]))
        print()

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

输出:

------Bob-------
Chapter 1: The Mandalorian: 152
Disney High School Musical: The Musical: The Series: Act Two: 117
Avatar: 109
Disney Mickey Mouse Clubhouse: Mickey Goes Fishing: 95
Spider-Man: 88
Marvel Studios Avengers: Endgame: 77
Float: 47

------Joe-------
Avatar: 109
Spider-Man: 88
Disney High School Musical: The Musical: The Series: Act Two: 87
Chapter 1: The Mandalorian: 82
Marvel Studios Avengers: Endgame: 77
Disney Mickey Mouse Clubhouse: Mickey Goes Fishing: 65
Float: 47

>>> 

我们有两个函数和一个生成器:

evaluate_score(我之前调用get_movie_score过)获取用户字典和电影字典,并根据用户的偏好返回该用户将分配给给定电影的分数(整数)。 get_all_scores是一个生成器,它接收一个用户和一个电影词典列表。它根据该用户获取所有电影的分数,并生成字典 - 每个字典包含两个键值对:电影标题和该用户分配的最终分数。main当我们想按降序打印最终结果时, 这个生成器将在函数后面有用。main是整个脚本的主要入口点。它首先打开并解析我们的两个 JSON 文件,然后为每个用户打印该用户对所有电影的得分的排序摘要(根据得分降序排列)。


推荐阅读