使用循环/递归镜像矩阵中的行?

时间:2015-12-05 14:37:38

标签: python recursion matrix

给定一些矩阵,我需要镜像矩阵中的所有行。例如

[[2, 1],
[4, 3]]

会变成

[[1, 2],
[3, 4]]

我设法为(2 x 2)-case做了。但我在镜像这样的事情时遇到了麻烦:

[[1, 2, 3, 4],
[1, 2, 3, 4]]

这必须成为

[[4, 3, 2, 1],
[4, 3, 2, 1]]

我想用循环/递归来做这件事。如果我使用递归,我可能会有基本步骤,首先交换最内层元素,然后从这里开始,我们将通过包括外部元素并交换它们来使矩阵更大。但是,我在递归步骤时遇到了麻烦。交换了最内层的元素之后,我想在矩阵中包含下一个最内层元素,并交换它们,然后像​​这样继续直到我们到达外部元素。如何在代码中实现?这就是我到目前为止所做的:

matrix = [[1, 2, 3, 4],
          [1, 2, 3, 4]]

def mirror(matrix):
    # This corresponds to the basic step. The two inner most elements get swapped.
    if len(matrix) == 2:
        for i in range(len(matrix)):
            for j in range(len(matrix)):
                # Store one element in a temporal variable
                temp = matrix[i][j]
                matrix[i][j] = matrix[i][len(matrix) - 1]
                matrix[i][len(matrix)-1] = temp
                return matrix

    else:
        # Recursion step
        for i in range(len(matrix)):
            for j in range(len(matrix)):
                return (matrix + mirror(matrix[(len(matrix) // 2) - 1 : len(matrix)]))

我认为递归步骤是错误的。我尝试使用切片运算符,但我不确定应该如何正确完成。任何有关此问题的帮助将不胜感激。

3 个答案:

答案 0 :(得分:4)

递归解决方案非常简单,只需递归整个数组,反转每个子数组:

arr= [[2, 1],
[4, 3]]

def reve(l):
    # if we have recursed across all sub arrays just return empty list
    if not l:
        return []
    # else reverse the first current sublist l[0] and recurse on the remaining sublists 
    return [l[0][::-1]] + reve(l[1:])


print(reve(arr))
[[1, 2], [3, 4]]

可以简明扼要地写成:

def reve(l):
    return [l[0][::-1]] + reve(l[1:]) if l else []

如果您想要 inplace

arr = [[1, 2, 3, 4],
     [1, 2, 3, 4]]

def reve(l):
    if not l:
        return 
    # call inplace list.reverse on each sublist
    l[0].reverse()
    return reve(l[1:])


reve(arr)

输出:

[[4, 3, 2, 1], [4, 3, 2, 1]]

最后,我们可以使用iter使用特殊方法__length__hint来完成您想要的 inplace ,而不会使用def reve(l): if l.__length_hint__() == 0: return sub = next(l) sub.reverse() return reve(l) reve(iter(arr)) print(arr) 进行切片:

[[4, 3, 2, 1], [4, 3, 2, 1]]

输出:

class ProfileSpyder(CrawlSpider):
  name = "Profile"
  allowed_domains = ["http://www.sherdog.com/fighter/"]
  start_urls = ["http://www.sherdog.com/fighter/Daniel-Cormier-52311", 
            "http://www.sherdog.com/fighter/Ronda-Rousey-73073"]

  Rules = (
      Rule(LinkExtractor(allow=('/fighter/')), callback='parse_item', follow=True)      
      )

  def parse_item(self, response):
    #Build absolute urls and sent new requests
    for href in   response.xpath("/html/body/div[3]/div[2]/div[1]/section[2]/div"):
        url = response.urljoin(href.extract())
        yield scrapy.Request(url, callback=self.parse_item)       
    #Parse item                     
    item = FighterProfile()
    item['Name'] =   response.xpath('.//section/div/h1/span[@class="fn"]/text()').extract()
    item['Birthdate'] = response.xpath('.//section/div/div/div/div/div/div/span/span[@itemprop="birthDate"]/text()').extract()
    item['Height'] = response.xpath('.//section/div/div/div/div/div/div/span[@class="item height"]/strong/text()').extract()
    item['Nationality'] = response.xpath('.//section[1]/div/div[1]/div[1]/div/div[1]/div[1]/span[2]/strong/text()').extract()
    yield item 

答案 1 :(得分:2)

这两个函数都可能使用map函数,但您也可以使用命令式for。关于我的递归方法,else语句引用列表的最终元素和第二元素之间的所有情况,它们被连接直到达到第一个元素。

我的递归方法:

a = [[1, 2, 3], 
     [5, 6, 7]]

def mirror(matrix):
    def revert(row):
        if len(row) == 1:
            return [row[0]]
        else:
            return [row[-1]] + revert(row[:-1]) # concatenates two lists.

    return [revert(row) for row in matrix]

mirror(a)

我的陈述方法:

def mirror(matrix):
    def revert(row):
        return row[::-1] # copies the array in reverse order

    return list(map(revert, matrix)) #<-for python3, and just map(...) for python2

mirror(a)

两个功能输出

[[3, 2, 1], [7, 6, 5]]

答案 2 :(得分:1)

实际上,更多Pythonic的做法是使用列表推导。你可以简单地通过以下方式做到这一点:

matrix = [[1, 2, 3, 4],
      [1, 2, 3, 4]]
reversed_matrix = (i[::-1] for i in matrix)

reversed_matrix将是一个生成器表达式。您可以将“()”替换为“[]”在列表理解中将其转换为列表。

i[::-1]使用切片运算符

就地反转数组