【问题标题】:How do I perform an operation on only the int part of lists?如何仅对列表的 int 部分执行操作?
【发布时间】:2018-05-10 21:18:44
【问题描述】:

我正在尝试为一堂课完成这项作业。说明说:

L 是一个列表列表。每个项目的第一项 sublist 是学生姓名和子列表中的其余项目 是等级值(floatint)。返回一个新的列表列表,其中 每个子列表的长度为 2,形式为 [student_name (str), average grade (float)]

>>> average_grade([['Bob', 56, 80, 72, 90], ['Alice', 60, 88, 44, 70], ['Joe', 44, 100, 80, 60, 50]])
[['Bob', 74.5], ['Alice', 65.5], ['Joe', 66.8]]

我的代码遇到的问题是我试图能够输入列表,但只能找到整数的平均值。到目前为止,我有这个:

for int in ['Bob', 'Alice', 'Joe']:
    return (map(L[sum(int)/len(int)]), map(L[sum(int)/len(int)]), map(L[sum(int)/len(int)]))

但是当我只输入一个列表时,我会得到这个:

builtins.TypeError: unsupported operand type(s) for +: 'int' and 'str'

我不确定在这里做什么。有什么帮助吗?

【问题讨论】:

  • 很抱歉,您的教师认为列表是 Python 中唯一可用的数据类型。
  • 我敢打赌切片在这里会很有用。
  • 不要使用int作为变量名,因为它会隐藏内置的int类型/函数。最好的方法是定义一个函数average_grade,然后使用问题陈述中建议的行average_grade([['Bob', 56, 80, 72, 90], ['Alice', 60, 88, 44, 70], ['Joe', 44, 100, 80, 60, 50]]) 对其进行测试,看看您的结果是否符合预期。您只需要从第一个添加每个子列表的成员,然后除以列表长度减去一(名称)。你可能在这里不需要map
  • 您可以将列表列表转换为“适当的”数据结构,例如字典列表并对其进行解析,以向您的老师表明您不同意他的实现:D

标签: python string list int


【解决方案1】:

您需要解构每个子列表。

def average_grade(grade_db):
    averages = []
    for student_grades in grade_db:
        name = student_grades[0]
        grades = student_grades[1:]
        # proceed to update results
    return averages

results = average_grade([['Bob', 56, 80, 72, 90], ['Alice', 60, 88, 44, 70], ['Joe', 44, 100, 80, 60, 50]])

第一次通过给定调用的循环,student_grades == ['Bob', 56, 80, 72, 90],第二次通过student_grades == ['Alice', 60, 88, 44, 70],依此类推。于是,第一次通过循环,name == 'Bob'grades == [56, 80, 72, 90]

【讨论】:

    【解决方案2】:
    def average_grade(L):
        return [[el[0], float(sum(el[1:]))/len(el[1:])] for el in L]
    

    这是列表理解方法。

    遍历列表列表L:为每个元素el 创建一个新列表,第一个元素为el[0](名称),第二个元素为平均值。使用float(sum(x))/len(x) 计算平均值,使用切片列表el[1:]。切片 el[1:] 表示从索引 1 到末尾获取 el 的子列表。这里需要float(),因为如果所有元素都是intsum() 可以是int

    【讨论】:

    • 在没有任何解释的情况下提供完整的解决方案不会帮助 OP。
    • 编辑了我的答案。我知道它可能不适合初学者,但恕我直言更pythonic。
    【解决方案3】:

    以下可能的实现:

    test = [['Bob', 56, 80, 72, 90], ['Alice', 60, 88, 44, 70], ['Joe', 44, 100, 80, 60, 50]]
    
    
    def mean(numbers):
        'Takes a list of numbers as argument and returns a float as their mean'
        return float(sum(numbers)) / max(len(numbers), 1)
    
    
    def average_grade(list_of_students):
        'Takes the lists of students as arguments and returns a list of lists containing the name and average grade'
        # We build an empty list to populate as we parse the list of students
        students = []
        # Parse each sublist of the list of students
        for student in list_of_students:
            # We add to the students list a new list made of:
            # element 0 is the first element of each sublist, meaning the name
            # element 1 is the result of applying the mean function over a list of floats created from each entry in the grades list
            students.append([student[0], mean([float(i) for i in student[1:]])])
        # And we return the students list
        return students
    
    print(average_grade(test))
    

    此实现可能存在的错误:

    如果您的某个成绩无法转换为浮点数怎么办?提示 -> 类型错误 在第 18 行进行转换。

    如果您的某个条目的成绩列表为空怎么办?

    如果你的名字不见了怎么办?

    如果您的条目数据不是列表怎么办?

    如果该列表完全为空怎么办?

    可能的教师问题: 为什么要在平均函数中实例化一个空列表?为什么不直接在外面声明呢?提示:在函数之外取线,然后调用 average_grade() 两次,看看会发生什么。

    为什么在计算平均值之前先转换为浮点数?这样做是为了避免计算非字符串/整数值的平均值。如果一个这样的值在成绩列表中,则脚本只会出错并显示 TypeError。您可以通过在 try/catch 子句中包含整个强制转换来规避此问题,并在遇到意外值时停止执行或直接丢弃它。

    【讨论】:

      【解决方案4】:

      这不是在 Python 中执行此操作的最有效方法,但我相信它会让初学者更清楚:

      final_list = []
      for sublist in lists:
          new_list = sublist[0] # Student name is always in the first index
          new_list.append(sum(sublist[1:]) / float(len(sublist[1:]))) # Take an average of the rest of the sublist and append it to the new list
          final_list.append(new_list) # Append the new_list e.g. ['Bob', 74.5] to the final list
      

      【讨论】:

      • new_list = [] 行的目的是什么?
      • 但这不是会让初学者在看到这个时认为必要的吗?
      • 另外,不要使用list 作为变量名,因为它会隐藏内置的list 类型。 编辑: 好的,sublist 更好。
      • @JonathanPorter 有明确的,然后有不必要的代码。如果读者还不知道sublist[0] 是一个列表,那么new_list = [] 就不会更有启发性了;他们只是会看到该行是不必要的,因为它会立即更改。在 Python 中有更好的方法来提供类型提示。
      • 但是创建一个包含一个元素的列表并没有什么隐含意义。
      【解决方案5】:

      这是尝试的解决方案(在问题中)正在做的事情:

      for int in ['Bob', 'Alice', 'Joe']:
        return (map(L[sum(int)/len(int)]), map(L[sum(int)/len(int)]), map(L[sum(int)/len(int)]))
      
      1. 它正在迭代名称“Bob”、“Alice”和“Joe”
      2. 在第一次迭代中,名为 int 的变量的值(顺便说一句,int 是一个 Python 关键字,因此请考虑选择一个更好的名称)的值为 'Bob'
      3. 此时,您的 return 语句转换为相当于 return (map(L[sum('Bob')/len('Bob'), map(L[sum('Bob')/len('Bob'), map(L[sum('Bob')/len('Bob'))

      请注意,您正在尝试对字符串对象求和。这会引发 TypeError

      builtins.TypeError: unsupported operand type(s) for +: 'int' and 'str'

      现在,深入研究一下,在上述错误中,'int' 类型在哪里出现。 sum 函数本质上是在尝试这样做:

      S = 0
      S = S + 'B'
      S = S + 'o'
      S = S + 'b'
      return S
      

      如您所见,我们不能将整数和字符串相加。没有意义。

      下面是一个可行的方法示例:

      map(lambda x: [x[0],sum(x[1:])/(float)(len(x)-1)], L)

      上述解决方案将遍历 L 中的每个项目。这里的项目是一个子列表,如 ['Bob', 56, 80, 72, 90]。然后,lambda 函数将此子列表映射到 ['Bob', sum([56, 80, 72, 90])/(float)(len(['Bob', 56, 80, 72, 90])-1)]

      每次迭代都会生成一个如上所述的映射列表,这是潜在的解决方案之一。 HTH。

      【讨论】:

      • 我在 2 小时前写了这行,但当时我的网络不工作 :)
      • 此答案因其长度和内容而被标记为低质量。 @dgumo 您可能想详细说明您的答案。提出的问题是关于理解类型操作,尽管您的答案可能会在一行中解决分配问题。学生将受益于对类型和列表操作的更广泛理解。
      • @Matt 感谢您指出答案的问题。为简洁的答案道歉。已编辑。希望现在有用:)
      【解决方案6】:

      您可以使用单行解决方案的列表理解:

      带循环:

      your_data=[['Bob', 56, 80, 72, 90], ['Alice', 60, 88, 44, 70], ['Joe', 44, 100, 80, 60, 50]]
      
      print([[item[0],sum(item[1:])/len(item[1:])] for item in your_data])
      

      输出:

      [['Bob', 74.5], ['Alice', 65.5], ['Joe', 66.8]]
      

      没有循环:

      如果您不想要循环,可以尝试使用 lambda:

      print(list(map(lambda x:[x[0],sum(x[1:])/len(x[1:])],your_data)))
      

      输出:

      [['Bob', 74.5], ['Alice', 65.5], ['Joe', 66.8]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 2020-09-22
        • 1970-01-01
        相关资源
        最近更新 更多