有没有更好的方法来可视化数组?

is there a better approach to visualize an array?

我想确保我用来显示数组的方法不是一种我不知道的更好方法的尴尬变通方法。到目前为止,我有很多感觉很尴尬。

对于间距元素 我设置了一个 TextMobject 数组的每个元素。next_to 前一个元素在右边有一个缓冲区。有没有更好的方法?

对于元素周围的框 我打算分别绘制数组的整个宽度的顶部和底部线,然后在元素之间绘制垂直线。我不打算关心以不同方式绘制这些框的动画,尽管我确实计划为此使用现有工具来突出显示元素。有没有更好的方法?

这是我目前的 "hello world" 代码。欢迎 suggestions/improvements 以上的任何人!

class ExampleArray(Scene):
    def construct(self):
        n = 6
        labels = TextMobject(* ["[" + str(index) + "]" for index in range(n)] )
        text = TextMobject( *[str(random.randint(0,10)) for i in range(n) ] )

        # space it out
        for i in range(1,len(text)):
            text[i].next_to(text[i-1], RIGHT, buff = 0.8)

        text.move_to(ORIGIN)


        for i in range(len(labels)):
            labels[i].scale(0.5)
            labels[i].next_to( text[i], DOWN, buff = 0.5)

        # can I just make a copy of top_line?
        top_line = Line(text.get_left() + LEFT, text.get_right() + RIGHT)
        bottom_line = Line(text.get_left() + LEFT, text.get_right() + RIGHT)
        top_line.next_to(text, UP)
        bottom_line.next_to(text, DOWN)

        self.add(labels)
        self.add(top_line, bottom_line)

        for i in range(len(text)):
            self.play(Write(text[i]))
            self.wait(0.1)

这就是我要做的方式。我建议您考虑以下事项:

  1. 当您不知道是否必须重用代码时,始终模块化您的代码。
  2. 纵向阅读总是比横向阅读更好。
  3. 避免使用索引(真正需要时使用它们)
  4. 使用 CONFIG 字典概括您将在整个场景中使用的变量。
  5. 较短的代码并不等同于更好的代码,必须始终在以下两者之间取得平衡:
    • 易于阅读
    • 易于维护
    • 易于扩展
class ExampleArray2(Scene):
    CONFIG = {
        "array_len": 6,
        "random_seed": 1, # with this you force to manim use other numbers
        # Change the random_seed to other number every time you want other 
        # random numbers
    }
    def construct(self):
        labels = TextMobject(*[
            f"[{index}]" 
            for index in range(self.array_len)
        ])
        text = TextMobject(*[
            str(random.randint(0,10))
            for i in range(self.array_len)
        ])
        # space it out
        text.arrange(RIGHT,buff=0.8)
        # See: https://github.com/3b1b/manim/blob/master/manimlib/mobject/mobject.py#L936

        for label,t in zip(labels,text): # I like to avoid using indexes
            label.scale(0.5)
            label.next_to(t,DOWN,buff=0.5)

        up_and_down_line = self.get_up_and_down_line(
            VGroup(text,labels),
            buff=0.7, # Distance between numbers and lines
            scale=1.4 # Scale of the line
        )

        self.play(
            *list(map(lambda x: Write(x,run_time=2),[text,labels])),
            *list(map(GrowFromCenter,up_and_down_line))
        )
        self.wait()

    def get_long_line(self,mob,y_direction,buff=0.5,scale=1):
        return Line(
            mob.get_corner(y_direction + LEFT), 
            mob.get_corner(y_direction + RIGHT)
        ).shift(y_direction*buff).scale(scale)

    def get_up_and_down_line(self,mob,**kwargs):
        return VGroup(
            self.get_long_line(mob,UP,**kwargs),
            self.get_long_line(mob,DOWN,**kwargs)
        )