【问题标题】:python list index out of range when passing an array through a function通过函数传递数组时python列表索引超出范围
【发布时间】:2019-05-31 21:47:52
【问题描述】:

首先,我无法理解这个问题,因此在解释时如有任何混淆,我深表歉意。

我目前正在制作一个健身房锻炼例程生成器,它将为某些肌肉组(也由我指定)随机提取一定数量(由我指定)的锻炼。我有一个名为array 的数组,看起来像这样;

[['Bench Press', 'Dumbell Press', 'Chest Press Machine', 'Cable Flies', 'Cable Crossover', 'Decline Bench Press', 'Angled Dips', 'Smith Machine Bench Press', 'Inner Chest Push'], 
['Incline Bench Press', 'Incline Dumbell Press', 'Incline Cable Flies', 'Incline Chest Press Machine', 'Incline Dumbell Flies', 'Raised Pushups', 'Smith Machine Incline Bench Press', 'Rotating Incline Dumbell Press', 'Inner Check Upwards Barbell Push'], 
['Barbell Overhead Press', 'Dumbell Overhead Press', 'Dumbell Lateral Raise', 'Face Pulls', 'Dumbell Front Raise', 'Reverse Flies', 'Smith Shoulder Press', 'Cable Side Raise', 'Behind Head Overhead Press'], 
['Dumbell Curls ', 'Hammer Curls', 'Preacher Curls', 'Machine Curls', 'Close Grip Chin Ups', 'Close Grip Pulldown', 'Half Rep Curls', 'Rotating Curls', 'Drop Set Curls'], 
['Cable Pushdowns', 'Overhead Dumbell Extensions', 'Overhead Barbell Extensions', 'Upright Dips', 'Skullcrushers', 'Close Grip Benchpress', 'Tricep Kickbacks', 'Overhead Rope Extensions', 'Drop Set Pushdowns'], 
['Lat Pulldowns', 'Pullups', 'Deadlifts', 'Bent Over Rows', 'Dumbell Rows', 'Rack Pulls', 'Upright Row', 'Low Rows', 'One Arm Cable Pull'], 
['Squats', 'Leg Press', 'Calf Raisers', 'Leg Extensions', 'Leg Curls', 'Lunges', 'Rear Kicks', 'Abductor', 'Adductor']]

带有二维数组的每个数组都包含针对不同肌肉群的练习。

现在我正在创建的例程是 4 天例程。第一天,正在生成胸部和三头肌(数组 1 和 5)。第 2 天是肩膀(阵列 3)。第 3 天是背部和二头肌(阵列 4 和 6),最后是第 4 天是腿(阵列 6)。

下面的函数应该是建立这个系统的:

def FourDays():
    global Day1
    Day1 = [4,0,0,0,2,0,0]
    global Day2
    Day2 = [0,0,5,0,0,0,0]
    global Day3
    Day3 = [0,0,0,2,0,4,0]
    global Day4
    Day4 = [0,0,0,0,0,0,5]

    Day1_routine = Routine_Maker3(array, Day1)
    Day2_routine = Routine_Maker3(array, Day2)
    Day3_routine = Routine_Maker3(array, Day3)
    Day4_routine = Routine_Maker3(array, Day4)

例如 - Day2(即肩膀),在数组的第三个索引中具有数字 5。这意味着来自第三个数组的 5 个练习,也就是包含肩部练习的数组。

这些变量(Day1Day2Day3Day4)然后被传递给以下函数,该函数负责从 array 获取适量的练习

def Routine_Maker3(array, exercises_per_day):
    old_routine = []
    pos = 0
    for i in range(7):
        if pos >= len(array):
            pos = 0
        temporal_array = [array[pos][j] for j in random.sample(range(9), exercises_per_day[pos])]
        old_routine.append(temporal_array)
        pos += 1
    print (old_routine)

    new_routine=[]
    for e in old_routine:
        new_routine += e
    print (new_routine)

请注意:Day1,2,3and4 应传递为exercises_per_day

这是一个应该输出的例子:

['Cable Crossover', 'Cable Flies', 'Smith Machine Bench Press', 'Inner Chest Push', 'Upright Dips', 'Overhead Dumbell Extensions']
['Behind Head Overhead Press', 'Dumbell Overhead Press', 'Smith Shoulder Press', 'Face Pulls', 'Dumbell Lateral Raise']
['Machine Curls', 'Close Grip Pulldown', 'Lat Pulldowns', 'One Arm Cable Pull', 'Pullups', 'Upright Row']
['Abductor', 'Rear Kicks', 'Lunges', 'Leg Curls', 'Squats']

我得到的错误是列表索引超出范围,它说这是这两行的问题:

Day1_routine = Routine_Maker4(array, Day1)

temporal_array = [array[pos][j] for j in random.sample(range(9), exercises_per_day[pos])]

【问题讨论】:

  • 我进行了编辑,使其更清晰
  • 你能告诉我你是如何初始化你的array 变量的吗?它看起来是一个 3d 数组...Nvm 你编辑了它。
  • 是的,很抱歉,当我复制数组时,我的复制和粘贴搞砸了 - 现在看起来就是数组的样子
  • 为什么你在for i in range(7)中设置range(7)
  • 这样它就可以遍历整个数组。 (确保它遍历数组中的每个值,即使它是 0)

标签: python arrays


【解决方案1】:

我有一个适合你的例程制造者的版本:

def Routine_Maker5(array, exercises_per_day):
    res = []
    for exercise_type, volume in enumerate(exercises_per_day):
        excercises = array[exercise_type][:]
        for _ in range(volume)    
            select = random.randint(0, len(excercises)-1)
            res.append(excercises.pop(select))
    return res

【讨论】:

  • 你能解释一下吗?exercise_type是什么
  • 这个问题是它不会删除列表中的值,这意味着我最终会得到重复
  • 我在这里也遇到了同样的问题。当我将它复制到我的程序中时,会发生同样的错误。
  • @DominicCulyer 现在它不会重复了。
  • @DominicCulyer exercise_type 是初始数组中的运动索引。例如:腿 6。
【解决方案2】:

这里有一个更简单的替代例程制造者方法。

def Routine_Maker3(array, exercises_per_day):
    routine = []
    for i in range(7):
        routine.extend(random.sample(array[i], exercises_per_day[i]))
    return routine

Routine_Maker3(array, Day1)

输出:

['Smith Machine Bench Press',
 'Inner Chest Push',
 'Bench Press',
 'Angled Dips',
 'Tricep Kickbacks',
 'Overhead Barbell Extensions']

基本上,random.sample() 函数接受一个数组和一个值 K,并从数组中返回 K 个随机值。正是你想要的。

您还使用了Routine_Maker4 而不是Routine_Maker3

当你试图将一个列表添加到另一个列表时,如果你想要一个平面的一维列表,你需要使用extend()而不是append()

【讨论】:

    【解决方案3】:

    让我们后退几步,更深入地了解您的问题。

    您想要做的是从列表列表(您称为数组)中获取具有唯一元素的随机子集。内置的random module 提供了专门的功能来执行此操作。我说的函数叫做random.sample()

    一般语法(取自文档是):

    random.sample(population, k)

    返回一个 k 长度的唯一元素列表 从种群序列或集合中选择。用于随机抽样 无需更换。

    返回一个包含总体元素的新列表,同时 保持原始人口不变。 [...]

    将此方法应用于您的问题将如下所示:

    import random
    
    exercises_0 = ['Bench Press', 'Dumbell Press', 'Chest Press Machine', 'Cable Flies', 'Cable Crossover', 'Decline Bench Press', 'Angled Dips', 'Smith Machine Bench Press', 'Inner Chest Push'] 
    exercises_1 = ['Incline Bench Press', 'Incline Dumbell Press', 'Incline Cable Flies', 'Incline Chest Press Machine', 'Incline Dumbell Flies', 'Raised Pushups', 'Smith Machine Incline Bench Press', 'Rotating Incline Dumbell Press', 'Inner Check Upwards Barbell Push']
    exercises_2 = ['Barbell Overhead Press', 'Dumbell Overhead Press', 'Dumbell Lateral Raise', 'Face Pulls', 'Dumbell Front Raise', 'Reverse Flies', 'Smith Shoulder Press', 'Cable Side Raise', 'Behind Head Overhead Press']
    exercises_3 = ['Dumbell Curls ', 'Hammer Curls', 'Preacher Curls', 'Machine Curls', 'Close Grip Chin Ups', 'Close Grip Pulldown', 'Half Rep Curls', 'Rotating Curls', 'Drop Set Curls']
    exercises_4 = ['Cable Pushdowns', 'Overhead Dumbell Extensions', 'Overhead Barbell Extensions', 'Upright Dips', 'Skullcrushers', 'Close Grip Benchpress', 'Tricep Kickbacks', 'Overhead Rope Extensions', 'Drop Set Pushdowns']
    exercises_5 = ['Lat Pulldowns', 'Pullups', 'Deadlifts', 'Bent Over Rows', 'Dumbell Rows', 'Rack Pulls', 'Upright Row', 'Low Rows', 'One Arm Cable Pull']
    exercises_6 = ['Squats', 'Leg Press', 'Calf Raisers', 'Leg Extensions', 'Leg Curls', 'Lunges', 'Rear Kicks', 'Abductor', 'Adductor']
    
    all_exercises = [exercises_0, exercises_1, exercises_2, exercises_3, exercises_4, exercises_5, exercises_6]
    
    days = [
        [4, 0, 0, 0, 2, 0, 0],
        [0, 0, 5, 0, 0, 0, 0],
        [0, 0, 0, 2, 0, 4, 0],
        [0, 0, 0, 0, 0, 0, 5]
        ]
    
    
    
    def get_exercises(day_number):
        output = []
        for idx, value in enumerate(days[day_number]):
            if value:
                # use `append` to get a list of lists
                output.append(random.sample(all_exercises[day_number], value))
                # use `extend` to get a single list
                # output.extend(random.sample(all_exercises[day_number], value))
        return output
    
    exercises_to_do = get_exercises(0)
    
    print(exercises_to_do)
    

    给你以下输出:

    [['Dumbell Press', 'Cable Flies', 'Decline Bench Press', 'Cable Crossover'], ['Cable Flies', 'Inner Chest Push']]
    

    【讨论】:

      【解决方案4】:

      试试这个简化的代码来帮助您避免未来的复杂错误:

      import random
      
      exercises = {"chest": ['Bench Press', 'Dumbell Press', 'Chest Press Machine', 'Cable Flies', 'Cable Crossover', 'Decline Bench Press', 'Angled Dips', 'Smith Machine Bench Press', 'Inner Chest Push'],
                   "shoulders": ['Barbell Overhead Press', 'Dumbell Overhead Press', 'Dumbell Lateral Raise', 'Face Pulls', 'Dumbell Front Raise', 'Reverse Flies', 'Smith Shoulder Press', 'Cable Side Raise', 'Behind Head Overhead Press'],
                   "back": ['Dumbell Curls ', 'Hammer Curls', 'Preacher Curls', 'Machine Curls', 'Close Grip Chin Ups', 'Close Grip Pulldown', 'Half Rep Curls', 'Rotating Curls', 'Drop Set Curls'],
                   "triceps": ['Cable Pushdowns', 'Overhead Dumbell Extensions', 'Overhead Barbell Extensions', 'Upright Dips', 'Skullcrushers', 'Close Grip Benchpress', 'Tricep Kickbacks', 'Overhead Rope Extensions', 'Drop Set Pushdowns'],
                   "biceps": ['Lat Pulldowns', 'Pullups', 'Deadlifts', 'Bent Over Rows', 'Dumbell Rows', 'Rack Pulls', 'Upright Row', 'Low Rows', 'One Arm Cable Pull'],
                   }
      
      
      def make_routine(*args, **kwargs):
          routine = []
          muscle_types = list(kwargs.keys())
          for muscle_type in muscle_types:
              muscle_exercises = exercises[muscle_type]
              exercises_per_day = kwargs[muscle_type]
              routine.extend(random.sample(muscle_exercises, exercises_per_day))
          return routine
      
      
      if __name__ == '__main__':
          day1_routine = make_routine(chest=4, triceps=2)
          day2_routine = make_routine(shoulders=5)
          print("day1_routine:", day1_routine)
          print("day2_routine:", day2_routine)
      
          # You get the idea
          # Just make you specifications as key word arguments in your calling function
          #
      

      【讨论】:

        猜你喜欢
        • 2023-03-16
        • 2021-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多