简体   繁体   English

在Python列表中查找所有矩形

[英]Finding all rectangles in Python list

I have a python list: 我有一个python列表:

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

I need to find all rectangles (how many rectangles are there) in this 2D array that meet this criteria: 我需要在此2D数组中找到满足以下条件的所有矩形(有多少个矩形):
1. All numbers in that one rectangle must be the same 1.一个矩形中的所有数字必须相同
2. Number from that rectangle can't be anywhere else in the array 2.该矩形中的数字不能在数组中的任何其他位置
3. Not really a criteria but some extra info: 3.并不是真正的标准,而是一些额外的信息:
Rectangles dimensions can be 1x1, 2x1, 2x2, 3x1, 3x2, 3x3, 3x4 and so on. 矩形尺寸可以是1x1、2x1、2x2、3x1、3x2、3x3、3x4等。

In this example there are 5 rectangles for numbers: 在此示例中,数字有5个矩形:

1, 2, 3, 4

and numbers 3, 1, 8 don't meet the criteria because: 而数字3、1、8不符合条件,因为:

5 - Breaks rule number 2 5-违反规则2
7 - Breaks rule number 2 7-违反规则2

I tried stuff like finding nearest elements that comparing them and if they match go down one row and so on but I couldn't do it so I hope someone could help. 我尝试过类似查找与它们进行比较的最接近元素,如果它们匹配则向下一行等等,但是我做不到,所以希望有人能提供帮助。 Thanks. 谢谢。

One approach is for each unique value, fit a rectangle over all instances of that value. 一种方法是针对每个唯一值,在该值的所有实例上拟合一个矩形。 If all values within that rectangle match, then you've met your criteria. 如果该矩形内的所有值都匹配,则说明您已满足条件。 Here it is implemented in code using numpy, printing values that match the criteria: 在这里,它是使用numpy在代码中实现的,打印出符合条件的值:

import numpy as np

arr = np.array([
    [3, 2, 2, 1, 4],
    [3, 2, 2, 7, 4],
    [8, 2, 2, 1, 3],
    [8, 8, 9, 9, 9],
    [8, 8, 1, 5, 1]
])
for n in np.unique(arr):
    y, x = np.where(arr == n)
    if (arr[y.min():y.max()+1, x.min():x.max()+1] == n).all():
        print(n)

Update 更新

Not as pretty but this something like this would not require numpy: 不那么漂亮,但是这样的事情不需要numpy:

lst = [
    [3, 2, 2, 1, 4],
    [3, 2, 2, 7, 4],
    [8, 2, 2, 1, 3],
    [8, 8, 9, 9, 9],
    [8, 8, 1, 5, 1]
]

for val in set([x for sub in lst for x in sub ]):
    y = [n for n, sub in enumerate(lst) if val in sub]
    if any(y):
        x = []
        for sub in [lst[n] for n in y]:
            x.extend([m for m, v in enumerate(sub) if v == val])

        rect = [i for sub in lst[min(y):max(y)+1] for i in sub[min(x):max(x)+1]]
        if all([i == val for i in rect]):
            print(val)

Further to the comment above from user3386109, here is the pure python code that will calculate the rectangle size from the top left coordinate to the bottom right coordinate and compare that to the total digits and see if they equal. 除了上面来自user3386109的注释,这是纯python代码,它将计算从左上角坐标到右下角坐标的矩形大小,并将其与总位数进行比较,看看它们是否相等。 If they do, then the digit is a rectangle. 如果是这样,则数字为矩形。

# create an empty result array
result = []

# check each digit one through nine
for num in range(1, 10):
    # create a list to store the coordinates of each found digit
    coords = []
    # rows loop
    for r in range(len(li)):
        # columns loop
        for c in range(len(li[0])):
            if li[r][c] == num:
                coords.append([r,c])
    # check for null coords list which means the digit is not in the matrix
    if len(coords) == 0:
        pass
    else:
        tl = coords[0]
        br = coords[-1]
        total = (br[0] - tl[0] + 1) * (br[1] - tl[1] + 1)
        if total == len(coords):
            result.append(num)
print('The digits that form rectangles are: ', result)

The result will look like this: 结果将如下所示:

The digits that form rectangles are:  [2, 4, 5, 7, 9]

Another approach is to consider using a pandas dataframe. 另一种方法是考虑使用熊猫数据框。

import pandas as pd

Make a dataframe from your list of numbers as follows: 从数字列表中制作一个数据框,如下所示:

df = pd.DataFrame([
[3, 2, 2, 1, 4],
[3, 2, 2, 7, 4],
[8, 2, 2, 1, 3],
[8, 8, 9, 9, 9],
[8, 8, 1, 5, 1]
])

Then you use a for loop to test each number 1-9 (I'm assuming 0 is not in your list?) and in the for loop you drop the rows and columns that don't have any of the number being tested. 然后,使用for循环测试每个1-9的数字(我假设列表中没有0?),然后在for循环中删除没有测试任何数字的行和列。 If the resulting frame is indeed a rectangle, then there should be no 'NaN's present. 如果生成的框架确实是矩形,则应该没有'NaN'。

For example, the digit 1 resulting frame looks like: 例如,数字1生成的帧如下所示:

      2   3   4
0    NaN 1.0 NaN
2    NaN 1.0 NaN
4    1.0 NaN 1.0

Whereas the digit 2 resulting frame looks like: 而数字2生成的帧如下所示:

     1   2
0   2.0 2.0
1   2.0 2.0
2   2.0 2.0

Check for NaN's being == 0 and you will have a rectangle. 检查NaN是否为== 0,您将得到一个矩形。 You also need to make sure the size of the field is not zero, as this would indicate a number not present. 您还需要确保该字段的大小不为零,因为这将指示不存在数字。 Here's the code: 这是代码:

result = []
for num in range(1, 10):
    df_dna = df[df == num].dropna(how="all", axis=0).dropna(how="all", axis=1)
    if df_dna.isnull().sum().sum() == 0 and df_dna.size != 0:
        result.append(num)
print("The numbers that form rectangles are:", result)

And your result looks like this: 您的结果如下所示:

The numbers that form rectangles are: [2, 4, 5, 7, 9]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM