用类实例替换数组中的元素 [英] Replace elements in array with class instances

查看:73
本文介绍了用类实例替换数组中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这类似于,所以请先阅读它,以了解我要做什么.

This is similar to this so please read it first to understand what I am trying to do.

现在,我想在有类实例时进行替换.类似:

Now, I want to make the replacement when I have class instances.Something like:

import numpy as np

class B():
    def __init__(self, a,b):
        self.a = a
        self.b = b


arr = np.array([ [1,2,3,4,5],[6,7,8,9,10] ])

b1 = np.array([B(100,'a'),
               B(11,'b'),
               B(300,'c'),
               B(33,'d')])

b2 = np.array([B(45,'a'),
              B(65,'b'),
              B(77,'c'),
              B(88,'d')])

# My d array will be like that and I will have to 
# run 3 loops as below . I can't change that
d = np.array([[b1],[b2]],dtype=object)

# Replace the elements
for i in d:
    for y in i:
        for idx,el in enumerate(y): 
            #y[idx].a = arr.reshape(-1,5) # 5 is the size of every sublength of arr
            #print(y[idx].a)
            pass

# Show the updated values
for i in d:       
    for y in i:
        for idx,x in enumerate(y):
            print(y[idx].a)

我不能使用b = arr.reshape(-1, a.size),因为它必须在循环之外运行.但是,正如我所说的,b数组将是y[idx].value,所以我不能仅仅将其放在第3个循环中,因为我将得到错误的结果,也不能将其放置在第3个循环之外,因为我将无法访问类实例的value部分.

I can't use the b = arr.reshape(-1, a.size) because this must run outside the loops.But, as I said the b array will be the y[idx].value , so I can't just place it in the 3rd loop because I will acquire wrong results, neither can I place it outside the 3rd loop because I will not have access to the value part of the class instance.

我希望我的结果是:

b1 = np.array([B(1,'a'),
               B(2,'b'),
               B(3,'c'),
               B(4,'d'),
               B(5,'d')])

b2 = np.array([B(6,'a'),
              B(7,'b'),
              B(8,'c'),
              B(9,'d'),
              B(10,'d')])

因此,我只想填充a部分,例如B类实例. 请注意,与以前(在上一个问题中)一样,B进行了扩展以容纳arr中的所有5个值.

So, I want to fill only the a part for example of the B class instances. And note,that as before ( in previous question) the B is expanded to hold all the 5 values from arr.

用几句话检查arr的每个子列表的长度(现在为5), 并相应地更新d值.因此,如果b1b2具有4个值,则它们必须成为5个值(arr的前5个值和arr的下5个值).

In a few words, check the length of each sublist of arr (which is 5 now), and update the d values accordingly.So, if b1 and b2 have 4 values, they must become 5 values (the first 5 values from arr and the next 5 values from arr).

推荐答案

所以我添加

print(d.shape)
print(d)

并获得

2249:~/mypy$ python3 stack42283851.py 
(2, 1, 4)
[[[<__main__.B object at 0xb71d760c> <__main__.B object at 0xb71d7aac>
   <__main__.B object at 0xb71d7acc> <__main__.B object at 0xb71e5cec>]]

 [[<__main__.B object at 0xb391718c> <__main__.B object at 0xb39171ac>
   <__main__.B object at 0xb39171cc> <__main__.B object at 0xb39171ec>]]]

__repr__添加到B我得到

1231:~/mypy$ python3 stack42283851.py 
(2, 1, 4)
[[[B(100, a) B(11, b) B(300, c) B(33, d)]]

 [[B(45, a) B(65, b) B(77, c) B(88, d)]]]

添加

import itertools
for a,b in itertools.zip_longest(arr[0,:],b1):
     print(a,b)

产生

1 B(100, a)
2 B(11, b)
3 B(300, c)
4 B(33, d)
5 None

更改为:

newlist = []
for a,b in itertools.zip_longest(arr[0,:],b1):
    if b is not None:
        new_b = B(a, b.b)
        last_b = b
    else:
        new_b = B(a, last_b.b)
    newlist.append(new_b)
print(np.array(newlist))

产生

[B(1, a) B(2, b) B(3, c) B(4, d) B(5, d)]

将其分配给b1,并重复a[1,:]b2.

Assign that to b1, and repeat for a[1,:] and b2.

为了更加简洁,我可以将new_b代码编写为函数,然后将循环重写为列表理解.

To be a little cleaner I could write that new_b code as a function, and rewrite the loop as a list comprehension.

是的,我可以就地修改b,例如

Yes, I could modify b in place, e.g.

b.a = a

,但是由于我需要创建一个新的B对象来替换None,所以何苦.我不能将新的B对象添加到原始的b1数组中.因此,通过列表创建新数组更为简单.

but since I need to create a new B object to replace the None, why bother. I can't add the new B object to the original b1 array. So it is simpler to create a new array via a list.

我可以使用以下方法就地更改db1:

I can do an in-place change of d and b1 with:

def replace(a,b):
    b.a = a
f = np.frompyfunc(replace, 2, 1)
f(arr[:,None,:4], d)      # produces array of None; ignore
print(d)
print(b1)

[[[B(1, a) B(2, b) B(3, c) B(4, d)]]  # chgd d

[[B(6, a) B(7, b) B(8, c) B(9, d)]]]
[B(1, a) B(2, b) B(3, c) B(4, d)]    # chgd b1

我只是将frompyfunc用作懒惰的方式来针对d广播arr并遍历所有元素.请注意,我必须更改arr以匹配d形状.同样,这不会添加任何新的B().显然,您不能就地进行此操作.

I'm just using frompyfunc as a lazy mans way of broadcasting arr against d and iterating over all elements. Note that I have to change arr to match d shape. Also this does not add any new B(). Obviously you can't do that in-place.

我的B

class B():
    def __init__(self, a,b):
        self.a = a
        self.b = b
    def __repr__(self):
        return 'B(%s, %s)'%(self.a, self.b)


frompyfunc一起玩:


Playing with frompyfunc some more:

getB_b = np.frompyfunc(lambda x: x.b, 1,1)   # fetch b attributes
print(getB_b(d))
#[[['a' 'b' 'c' 'd']]
#
# [['a' 'b' 'c' 'd']]]

mkB = np.frompyfunc(B, 2,1)   # build array of B() with broadcasting
print(mkB(arr, ['a','b','c','d','e']))
# [[B(1, a) B(2, b) B(3, c) B(4, d) B(5, e)]
#  [B(6, a) B(7, b) B(8, c) B(9, d) B(10, e)]]

print(mkB(arr[:,:4], getB_b(d[:,0,:])))
# [[B(1, a) B(2, b) B(3, c) B(4, d)]
#  [B(6, a) B(7, b) B(8, c) B(9, d)]]


编辑评论

arr1 = np.array([ [1,2],[6,7] ])
newlist = []
for a,b in itertools.zip_longest(arr1[0,:],b1):
    if b is not None:
        new_b = B(a, b.b)
        last_b = b
    else:
        new_b = B(a, last_b.b)
    newlist.append(new_b)
print(np.array(newlist))

产生

[B(1, a) B(2, b) B(None, c) B(None, d)]

arr较短时,a将为None(而不是b);所以我们需要对此进行测试

When arr is shorter, a will be None (instead of b); so we need to test for that

def foo(arr,bn):
    newlist = []
    for a,b in itertools.zip_longest(arr,bn):
        print(a,b)
        if a is None:
            pass
        else:
            if b is not None:
                new_b = B(a, b.b)
                last_b = b
            else:
                new_b = B(a, last_b.b)
            newlist.append(new_b)
    return newlist
print(np.array(foo(arr1[0,:],b1)))  # arr1 shorter
print(np.array(foo(arr[0,:], b2)))  # arr longer 

测试:

1 B(1, a)
2 B(2, b)
None B(3, c)
None B(4, d)
[B(1, a) B(2, b)]

1 B(6, a)
2 B(7, b)
3 B(8, c)
4 B(9, d)
5 None
[B(1, a) B(2, b) B(3, c) B(4, d) B(5, d)]

没有什么特别的或不可思议的;只需确保我正确地完成了if测试和缩进即可.

Nothing special or magical; just a matter making sure I get the if tests and indentation right.

这篇关于用类实例替换数组中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆