由于PHP中的数组深度问题,从Python接收此数组会被删除省略号(“...”)。我想在返回php之前用Python处理数组。
澄清:我需要保持内部集[135,121,81]。这些是R,G,B值,我与多次出现的组合在一起。集合中的值需要维持[1,2,3]序列,而不是[1,2,3,4,5,6,7,8],如下面的一些答案所示。
您如何将此3D numpy.ndarray
简化为一系列独特的RGB三元组?
以下是Python如何打印数组:
[[[135 121 81]
[135 121 81]
[135 121 81]
...,
[135 121 81]
[135 121 81]
[135 121 81]]
[[135 121 81]
[135 121 81]
[135 121 81]
...,
[135 121 81]
[135 121 81]
[135 121 81]]
[[ 67 68 29]
[135 121 81]
[ 67 68 29]
...,
[135 121 81]
[135 121 81]
[135 121 81]]
...,
[[200 170 19]
[200 170 19]
[200 170 19]
...,
[ 67 68 29]
[ 67 68 29]
[ 67 68 29]]
[[200 170 19]
[200 170 19]
[200 170 19]
...,
[116 146 15]
[116 146 15]
[116 146 15]]
[[200 170 19]
[200 170 19]
[200 170 19]
...,
[116 146 15]
[116 146 15]
[116 146 15]]]
以下是我尝试过的代码:
def uniquify(arr)
keys = []
for c in arr:
if not c in keys:
keys[c] = 1
else:
keys[c] += 1
return keys
result = uniquify(items)
答案 0 :(得分:2)
根据您的“数组”的表示,看起来您正在使用numpy.ndarray
。如果是这种情况,这就变成了一个非常简单的问题 - 您可以使用.flat
属性转换为一维可迭代的简单。要使其独一无二,您只需使用set
:
set(array.flat)
这会给你一套,但你可以很容易地从中得到一个列表:
list(set(array.flat))
以下是它的工作原理:
>>> array = np.zeros((10,12,42,53))
>>> list(set(array.flat))
[0.0]
作为旁注,还有np.unique
,它也会为您提供阵列的独特元素。
>>> array = np.zeros((10,12),dtype=int)
>>> print array
[[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0]]
>>> np.unique(array)
array([0])
>>> array[0,5] = 1
>>> array[4,10] = 42
>>> np.unique(array)
array([ 0, 1, 42])
我想我终于找到了这个:
from itertools import product
items = set(tuple(a[itr+(slice(None),)]) for itr in product(*[range(x) for x in a.shape[:-1]]))
print items
似乎工作。呼!
这是如何工作的 - 您想要保存为三元组的部分可以访问:
array[X,Y,:]
因此,我们只需要遍历X
和Y
的所有组合。这正是itertools.product
的好处。我们可以在任意数量的维度中获得有效的X
和Y
:
[range(x) for x in array.shape[:-1]]
所以我们将其传递给产品:
indices_generator = product(*[range(x) for x in array.shape[:-1]])
现在我们有了一些能够生成第一个索引的东西 - 我们只需要构造一个元组来传递给__getitem__
numpy将其解释为(X,Y,:)
- 这很简单,我们已经从indices_generator获取(X,Y)
- 我们只需要处理一个emtpy切片:
all_items = ( array[idx+(slice(None),)] for idx in indices_generator )
现在我们可以循环遍历all_items,寻找具有集合的唯一的:
unique_items = set(tuple(item) for item in all_items)
现在把它转回一个列表,或一个numpy数组或任何你想要的东西,以便将它传回PHP。
答案 1 :(得分:1)
查看itertools
文档中的食谱。有flatten
和unique_everseen
函数完全符合您的要求。
因此,您可以复制并粘贴它们。或者您只需pip install more-itertools
即可导入它们。现在,您可以将3D数组展平为2D,并使用unique_everseen
...
除了一个问题。 2D数组的元素是list
s,它们是不可清除的,因此您必须将它们转换为可哈希的东西。但这很容易:
def uniquify(arr3d):
return unique_everseen(flatten(arr3d), tuple)
就是这样。
如果你在粘贴它们时查看这些函数的实现,它们就非常简单了。这里唯一真正的技巧是使用set
来保存到目前为止看到的值:sets只保存每个唯一元素的一个副本(并且可以非常快速地确定元素是否已经存在于集合中)。
事实上,如果你不需要保留订单,那就更简单了:
def uniquify(arr3d):
return set(tuple(x) for x in flatten(arr3d))
作为测试,我复制了你的字符串并将其转换为实际的Python列表显示,然后执行了此操作:
inarray = [[[135, 121, 81],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81]],
[[135, 121, 81],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81]],
[[67, 68, 29],
[135, 121, 81],
[67, 68, 29],
[135, 121, 81],
[135, 121, 81],
[135, 121, 81]],
[[200, 170, 19],
[200, 170, 19],
[200, 170, 19],
[67, 68, 29],
[67, 68, 29],
[67, 68, 29]],
[[200, 170, 19],
[200, 170, 19],
[200, 170, 19],
[116, 146, 15],
[116, 146, 15],
[116, 146, 15]],
[[200, 170, 19],
[200, 170, 19],
[200, 170, 19],
[116, 146, 15],
[116, 146, 15],
[116, 146, 15]]]
for val in uniquify(inarray):
print(val)
输出结果为:
[135, 121, 81]
[67, 68, 29]
[200, 170, 19]
[116, 146, 15]
这就是你想要的吗?
如果您想将其作为list
的{{1}},那就是:
list
如果您使用的是简单的array2d = list(uniquify(array3d))
而不是set
,那么这些将是unique_everseen
而不是tuple
,因此如果您需要list
} list
s:
list
答案 2 :(得分:0)
itertools
是你的朋友:
>>> import itertools
>>> array = [1,1,1,2,2,2,3,3,3,4,5,6,6,6]
>>> [x[0] for x in itertools.groupby(array)]
[1, 2, 3, 4, 5, 6]
例如:
array = [[[135,121,81],
[135,121,81],
[135,121,81],
[135,121,81],
[135,121,81],
[135,121,81]],
[[135,121,81],
[135,121,81],
[135,121,81],
[135,121,81],
[135,121,81],
[135,121,81]],
[[67,68,29],
[135,121,81],
[67,68,29],
[135,121,81],
[135,121,81],
[135,121,81]]]
import itertools
new_array = list()
for inner in array:
new_inner = [x[0] for x in itertools.groupby(inner)]
new_array.append(new_inner)
产地:
[ [ [135, 121, 81] ],
[ [135, 121, 81] ],
[ [67, 68, 29],
[135, 121, 81],
[67, 68, 29],
[135, 121, 81] ] ]
不完全独特,但您可以将inner
排序为唯一。
答案 3 :(得分:0)
假设python list
看起来像[[[1,2,3], [4,5,6]], [[7,8,9]]]
(即list
list
integers
mylist = [[[1,2,3], [4,5,6]], [[7,8,9]]]
items = set()
for sublist in mylist:
for subsublist in sublist:
for item in subsublist:
items.add(item)
list
如果您特别需要items = list(items)
,则可以将其投射为:set
list
是一种类似于set
的数据类型,但不包含重复项。
mylist = [[[1,2,3], [4,5,6]], [[7,8,9]]]
items = []
for sublist in mylist:
for subsublist in sublist:
for item in subsublist:
if not item in items:
items.add(item)
数据类型的副作用是不保留插入顺序 - 如果这对您很重要,则需要以下内容:
mylist = [[[1,2,3], [4,5,6]], [[7,8,9], [1,2,3]]]
items = []
for sublist in mylist:
for item in sublist:
if not item in items:
items.append(item)
# items = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
编辑:根据你的编辑,你可能想要这个:
{{1}}