多维枚举,如何避免代码宏生成
Multidimensional Enumeration, how to avoid Code Macro Generation
所以我有一个名为 Object 的多维列表,有 n 个维度
我正在为这个对象的所有元素执行一个过程(可以是任何东西,包括其他多维列表)
所以我开始生成以下枚举对象的归纳方式
案例 1:1-d(列表)
i = 0
while(i < len(Object)):
f(Object[i])
i+=1
案例 2:2-d(列表中的列表)
i = 0
while(i < len(Object)):
j = 0
while(j < len(Object[i][j])):
f(Object[i])
j+=1
i+=1
至此直观明显,可以通过以下代码遍历n维对象
indexarray = [] #multi dimensional index structure
i = 0
while(i < n):
indexarray.append(0)
i+=1
#Prepared the indices
while(indexarray[0] < len(Object)):
indexarray[1] = 0
while(indexarray[1] < len(Object[indexarray[0]])):
indexarray[2] = 0
while(indexarray[2] < len(Object[indexarray[0]][indexarray[1]])):
indexarray[3] = 0
.
.
.
indexarray[n-1] = 0
while(indexarray[n-1] < len(Object[indexarray[0]][...]))
f(Object[...])
indexarray[n-1]+=1
.
.
.
indexarray[2]+=1
indexarray[1]+=1
indexarray[0]+=1
唯一的问题是我将不得不创建一个自己生成代码的子例程。我个人认为那太棒了!但是...也许还有更多 "elegant" 方法可以做到这一点。应该如何进行呢?
递归怎么样?
def traverse_object_dfs(myobject):
for irun in range(len(myobject)):
traverse_object_dfs(myobject[irun])
f(myobject)
但问题是,您的函数 f
应用于每个深度。所以你需要找出你是否处于第二低的递归级别。您的对象是否支持 ndim
之类的东西,即您事先知道维度?否则我们可以尝试询问最内层元素是否支持 __len__
操作(或者询问它是否是您的多维数组对象的实例,如果您的最内层元素也支持 __len__
则您应该这样做为了避免无限递归,感谢您在评论中再次指出这一点!):
def f(myobject):
print myobject
def traverse_object_dfs(myobject):
for irun in range(len(myobject)):
if hasattr(myobject[irun], '__len__'): ## or isinstance(myobject[irun], YourClass) # if innermost elements also support '__len__':
traverse_object_dfs(myobject[irun])
else:
f(myobject[irun])
和
x = [[[1,2],[3,4]],[[5,6],[7,8]]]
traverse_object_dfs(x)
打印
1
2
3
4
5
6
7
8
您可以使用递归遍历列表的嵌套元素,即本身是列表(或可能是元组)的元素。此函数将遍历给定列表的所有元素,根据需要下降到嵌套列表和元组:
def visit_item(item):
print 'visit_item(): called on %r' % item
def traverse_list(l):
for item in l:
if isinstance(item, (list, tuple)):
traverse_list(item)
else:
visit_item(item)
visit_item()
与列表的每个项目一起调用,嵌套列表除外。这是一个例子 运行:
>>> l = [[1, 2, 3, 4], 'hello', 444, ['a', 'b', [7, 7, [3, 2, 1], 7, 7, 7], 'c']]
>>> traverse_list(l)
visit_item(): called on 1
visit_item(): called on 2
visit_item(): called on 3
visit_item(): called on 4
visit_item(): called on 'hello'
visit_item(): called on 444
visit_item(): called on 'a'
visit_item(): called on 'b'
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 3
visit_item(): called on 2
visit_item(): called on 1
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 'c'
对 traverse_list()
的一个小修改允许它 "visit" 实际的嵌套列表对象,如果需要的话(我不确定你的问题):
def traverse_list(l):
for item in l:
visit_item(item)
if isinstance(item, (list, tuple)):
traverse_list(item)
>>> traverse_list(l)
visit_item(): called on [1, 2, 3, 4]
visit_item(): called on 1
visit_item(): called on 2
visit_item(): called on 3
visit_item(): called on 4
visit_item(): called on 'hello'
visit_item(): called on 444
visit_item(): called on ['a', 'b', [7, 7, [3, 2, 1], 7, 7, 7], 'c']
visit_item(): called on 'a'
visit_item(): called on 'b'
visit_item(): called on [7, 7, [3, 2, 1], 7, 7, 7]
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on [3, 2, 1]
visit_item(): called on 3
visit_item(): called on 2
visit_item(): called on 1
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 'c'
所以我有一个名为 Object 的多维列表,有 n 个维度
我正在为这个对象的所有元素执行一个过程(可以是任何东西,包括其他多维列表)
所以我开始生成以下枚举对象的归纳方式
案例 1:1-d(列表)
i = 0
while(i < len(Object)):
f(Object[i])
i+=1
案例 2:2-d(列表中的列表)
i = 0
while(i < len(Object)):
j = 0
while(j < len(Object[i][j])):
f(Object[i])
j+=1
i+=1
至此直观明显,可以通过以下代码遍历n维对象
indexarray = [] #multi dimensional index structure
i = 0
while(i < n):
indexarray.append(0)
i+=1
#Prepared the indices
while(indexarray[0] < len(Object)):
indexarray[1] = 0
while(indexarray[1] < len(Object[indexarray[0]])):
indexarray[2] = 0
while(indexarray[2] < len(Object[indexarray[0]][indexarray[1]])):
indexarray[3] = 0
.
.
.
indexarray[n-1] = 0
while(indexarray[n-1] < len(Object[indexarray[0]][...]))
f(Object[...])
indexarray[n-1]+=1
.
.
.
indexarray[2]+=1
indexarray[1]+=1
indexarray[0]+=1
唯一的问题是我将不得不创建一个自己生成代码的子例程。我个人认为那太棒了!但是...也许还有更多 "elegant" 方法可以做到这一点。应该如何进行呢?
递归怎么样?
def traverse_object_dfs(myobject):
for irun in range(len(myobject)):
traverse_object_dfs(myobject[irun])
f(myobject)
但问题是,您的函数 f
应用于每个深度。所以你需要找出你是否处于第二低的递归级别。您的对象是否支持 ndim
之类的东西,即您事先知道维度?否则我们可以尝试询问最内层元素是否支持 __len__
操作(或者询问它是否是您的多维数组对象的实例,如果您的最内层元素也支持 __len__
则您应该这样做为了避免无限递归,感谢您在评论中再次指出这一点!):
def f(myobject):
print myobject
def traverse_object_dfs(myobject):
for irun in range(len(myobject)):
if hasattr(myobject[irun], '__len__'): ## or isinstance(myobject[irun], YourClass) # if innermost elements also support '__len__':
traverse_object_dfs(myobject[irun])
else:
f(myobject[irun])
和
x = [[[1,2],[3,4]],[[5,6],[7,8]]]
traverse_object_dfs(x)
打印
1
2
3
4
5
6
7
8
您可以使用递归遍历列表的嵌套元素,即本身是列表(或可能是元组)的元素。此函数将遍历给定列表的所有元素,根据需要下降到嵌套列表和元组:
def visit_item(item):
print 'visit_item(): called on %r' % item
def traverse_list(l):
for item in l:
if isinstance(item, (list, tuple)):
traverse_list(item)
else:
visit_item(item)
visit_item()
与列表的每个项目一起调用,嵌套列表除外。这是一个例子 运行:
>>> l = [[1, 2, 3, 4], 'hello', 444, ['a', 'b', [7, 7, [3, 2, 1], 7, 7, 7], 'c']]
>>> traverse_list(l)
visit_item(): called on 1
visit_item(): called on 2
visit_item(): called on 3
visit_item(): called on 4
visit_item(): called on 'hello'
visit_item(): called on 444
visit_item(): called on 'a'
visit_item(): called on 'b'
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 3
visit_item(): called on 2
visit_item(): called on 1
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 'c'
对 traverse_list()
的一个小修改允许它 "visit" 实际的嵌套列表对象,如果需要的话(我不确定你的问题):
def traverse_list(l):
for item in l:
visit_item(item)
if isinstance(item, (list, tuple)):
traverse_list(item)
>>> traverse_list(l)
visit_item(): called on [1, 2, 3, 4]
visit_item(): called on 1
visit_item(): called on 2
visit_item(): called on 3
visit_item(): called on 4
visit_item(): called on 'hello'
visit_item(): called on 444
visit_item(): called on ['a', 'b', [7, 7, [3, 2, 1], 7, 7, 7], 'c']
visit_item(): called on 'a'
visit_item(): called on 'b'
visit_item(): called on [7, 7, [3, 2, 1], 7, 7, 7]
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on [3, 2, 1]
visit_item(): called on 3
visit_item(): called on 2
visit_item(): called on 1
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 7
visit_item(): called on 'c'