(在 Python 3.8 中)填写列表以保持它们在长度和平均值上相似?

(In Python 3.8) filling in lists to mantain them similar in length and average?

我需要在 3 个单独的列表中分配一些值。 这些值是即时生成的,但都包含在 0-6 范围内。

关键是这些值应该放在三个列表中,这样每个列表的平均值就不会与其他列表相差太多。列表的长度也需要相似。

因此,目标是逐步填充这些列表,以尽可能保持所有列表的平均值和大小一致。

由于我没有找到任何内置函数来执行此操作,因此我实现了一个代码来跟踪列表长度并尽量使它们的平均值尽可能接近。您可以尝试并改进它以更好地适应您的情况。

class Data:
    def __init__(self):
        """Init the three lists."""
        self.a = []
        self.b = []
        self.c = []

    @staticmethod
    def get_average(data: list):
        """Get average value of a list."""
        try:
            return sum(data) / len(data)
        except ZeroDivisionError:
            return 0

    def get_shortest(self):
        """Return list with the shortest length."""
        shortest_length = min(len(self.a), len(self.b), len(self.c))

        if len(self.a) == shortest_length:
            return self.a
        elif len(self.b) == shortest_length:
            return self.b
        else:
            return self.c

    def get_smallest(self):
        """Return list with the smallest average value."""
        smallest_average = min(self.get_average(self.a), self.get_average(self.b), self.get_average(self.c))

        if self.get_average(self.a) == smallest_average:
            return self.a
        elif self.get_average(self.b) == smallest_average:
            return self.b
        else:
            return self.c

    def get_highest(self):
        """Return list with the highest average value."""
        highest_average = max(self.get_average(self.a), self.get_average(self.b), self.get_average(self.c))

        if self.get_average(self.a) == highest_average:
            return self.a
        elif self.get_average(self.b) == highest_average:
            return self.b
        else:
            return self.c

    def add_number(self, num):
        """Add number to one of the lists."""
        shortest = self.get_shortest()
        smallest = self.get_smallest()
        highest = self.get_highest()

        # Lists must not differ by more than two elements
        if len(smallest) - len(shortest) >= 2 or len(highest) - len(shortest) >= 2:
            shortest.append(num)
        else:
            # Test if the number uppers the smallest average
            initial_avg = self.get_average(smallest)
            smallest.append(number)
            final_avg = self.get_average(smallest)
            if final_avg > initial_avg:
                return
            else:
                smallest.pop()

            # Test if the number lowers the highest average
            initial_avg = self.get_average(highest)
            highest.append(number)
            final_avg = self.get_average(highest)
            if final_avg < initial_avg:
                return
            else:
                highest.pop()

            # Last resort
            shortest.append(num)


d = Data()

value = input("Add number: ")

while value != 'e':
    try:
        number = int(value)
    except ValueError:
        break

    d.add_number(number)

    print(f"List a: {d.a}, avg. {d.get_average(d.a)}")
    print(f"List b: {d.b}, avg. {d.get_average(d.b)}")
    print(f"List c: {d.c}, avg. {d.get_average(d.c)}")

    value = input("Add number:")