【问题标题】:Reverse a list without using built-in functions在不使用内置函数的情况下反转列表
【发布时间】:2017-01-22 23:54:34
【问题描述】:

我正在使用 Python 3.5。

作为问题的一部分,我正在尝试设计一个将列表作为输入并将其还原的函数。因此,如果x = [a, b, c] 函数将生成x = [c, b, a]

问题是,我不允许使用任何内置函数,这让我陷入了困境。我最初的想法是函数内的以下循环:

for revert in range(1, len(x) + 1):
    y.append(x[-revert])

而且它有效。但问题是我使用的是len(x),我认为这是一个内置函数,对吗?

于是我四处搜索,做了以下非常简单的代码:

y = x[::-1]

这正是我想要的,但它似乎太简单/容易了,我不确定"::" 是否算作一个函数。

所以我想知道是否有人对如何手动设计所述功能有任何提示/想法?当你不能使用任何内置函数时,这似乎真的很难,而且我已经卡了很长一段时间了。

【问题讨论】:

    标签: python list python-3.x


    【解决方案1】:

    rangelen 都是 built-in functions。由于list 方法 被接受,您可以使用insert 来执行此操作。 确实很慢*,但它可以在不使用任何内置插件的情况下为 small 列表完成工作:

    def rev(l):
        r = []
        for i in l:
            r.insert(0, i)
        return r
    

    通过在第零个位置连续插入,您最终会得到输入列表的反转版本:

    >>> print(rev([1, 2, 3, 4]))
    [4, 3, 2, 1]
    

    在做:

    def rev(l): 
        return l[::-1] 
    

    也可以被认为是一种解决方案。 ::-1:: 有不同的结果)不是函数(它是一个切片),[] 又是一个列表方法。此外,与insert 相比,它更快且更具可读性;只要确保你能够理解和解释它。可以在 in this S.O answer.

    中找到关于其工作原理的很好的解释

    *Reeaaalllyyyy 慢,请参阅 juanpa.arrivillaga 的酷情节答案和 appendpop 并查看列表中的就地 reverse,如 Yoav Glazner 的回答中所做的那样。

    【讨论】:

      【解决方案2】:

      :: 不是一个函数,它是一个 python 文字。还有[]

      如何检查::, [] 是否是函数。很简单,

          import dis
          a = [1,2]
          dis.dis(compile('a[::-1]', '', 'eval'))
            1           0 LOAD_NAME                0 (a)
                        3 LOAD_CONST               0 (None)
                        6 LOAD_CONST               0 (None)
                        9 LOAD_CONST               2 (-1)
                       12 BUILD_SLICE              3
                       15 BINARY_SUBSCR
                       16 RETURN_VALUE
      

      如果::,[]是函数,你应该在a[::-1]语句执行的python指令中找到标签CALL_FUNCTION。所以,他们不是。

      看看当你调用一个函数时python指令是什么样子的,比如说list()函数

      >>> dis.dis(compile('list()', '', 'eval'))
        1           0 LOAD_NAME                0 (list)
                    3 CALL_FUNCTION            0
                    6 RETURN_VALUE
      

      所以,基本上

      def rev(f):
          return f[::-1]
      

      工作正常。但是,如果您的问题是家庭作业或老师发送的,我认为您应该像 Jim 在他的回答中建议的那样做。但是,您可以将此最快的方式添加为附注。

      如果你的老师抱怨[::-1] 符号,给他看我给你的例子。

      【讨论】:

        【解决方案3】:

        另一种方式(只是为了完整性:))

        def another_reverse(lst):
            new_lst = lst.copy() # make a copy if you don't want to ruin lst...
            new_lst.reverse() # notice! this will reverse it in place
            return new_lst
        

        【讨论】:

          【解决方案4】:

          这是一个不使用内置函数但依赖于列表方法的解决方案。正如您的规范所暗示的那样,它就地反转:

          >>> x = [1,2,3,4]
          >>> def reverse(seq):
          ...   temp = []
          ...   while seq:
          ...     temp.append(seq.pop())
          ...   seq[:] = temp
          ... 
          >>> reverse(x)
          >>> x
          [4, 3, 2, 1]
          >>> 
          

          预计到达时间

          吉姆,你在位置 0 使用 insert 的回答让我发疯了!该解决方案是二次时间!您可以将appendpop 与临时列表一起使用,以使用简单的列表方法实现线性时间。请参阅(reverse 为蓝色,rev 为绿色):

          如果感觉有点像使用seq[:] = temp“作弊”,我们总是可以循环temp并将每个项目附加到seq中,时间复杂度仍然是线性的,但可能更慢,因为它不是使用基于 C 的内部结构。

          【讨论】:

          • 哦,是的,速度很慢。我也讨厌自己:-)
          【解决方案5】:

          你的例子有效:

          y = x[::-1]
          

          使用 Python slices notation 在我假设您请求的意义上不是一个函数。本质上:: 充当分隔符。更详细的代码版本是:

          y = x[len(x):None:-1]
          

          y = x[start:end:step]
          

          我可能不会抱怨 python 让你的生活变得非常非常轻松。


          编辑得超级迂腐。有人可能会争辩说,调用 [] 完全是在使用内置的 Python 函数,因为它实际上是 __getitem__() 方法的语法糖。

          x.__getitem__(0) == x[0]
          

          使用:: 确实会使用slice() 对象。

          x.__getitem__(slice(len(x), None, -1) == x[::-1]
          

          但是...如果您要争论这一点,那么您在 python 中编写的任何内容都将使用内置的 python 函数。

          【讨论】:

            【解决方案6】:

            另一种完整性方式,range() 采用可选的 step 参数,可让您后退列表:

            def reverse_list(l):
                return [l[i] for i in range(len(l)-1, -1, -1)]
            

            【讨论】:

            • range 是内置的 - OP 询问如何不使用内置
            • 我认为他的意思是不使用内置的 reversed()list.reverse(),因为 OP 在他们的示例中使用了 range()。正如另一个答案还指出,在 Python 中不使用内置函数几乎是不可能的,因为即使 list[x] 也会调用列表的内置方法。
            • 这个答案也可能对将来寻找不使用reversed()/list.reverse() 来反转列表的其他人有用
            【解决方案7】:

            实现这一点的最 Pythonic 和最有效的方法是列表切片。而且,由于您提到您不需要任何内置功能,它完全满足您的要求。例如:

            >>> def reverse_list(list_obj):
            ...     return list_obj[::-1]
            ...
            >>> reverse_list([1, 3, 5 , 3, 7])
            [7, 3, 5, 3, 1]
            

            【讨论】:

              【解决方案8】:

              只需从右到左迭代列表以获取项目..

              a = [1,2,3,4]
              
              def reverse_the_list(a):
                 reversed_list = []
                 for i in range(0, len(a)):
                   reversed_list.append(a[len(a) - i - 1])
                 return reversed_list
              
              new_list = reverse_the_list(a)
              print new_list
              

              【讨论】:

                猜你喜欢
                • 2021-12-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-02-20
                • 2020-10-14
                相关资源
                最近更新 更多