Python 重新排列列表中元素的更好方法

Python 重新排列列表中元素的更好方法,python,algorithm,numpy,Python,Algorithm,Numpy,假设我们有这样的表格CPD(条件概率分布) | C | C_0 | C_0 | C_0 | C_0 | C_1 | C_1 | C_1 | C_1 | | B | B_0 | B_0 | B_1 | B_1 | B_0 | B_0 | B_1 | B_1 | | A | A_0 | A_1 | A_0 | A_1 | A_0 | A_1 | A_0 | A_1 | | J_0 | 0.9 | 0.3 | 0.9 | 0.3 | 0.8 | 0.8 | 0.4 | 0.4 | | J_

假设我们有这样的表格CPD(条件概率分布)

| C   | C_0 | C_0 | C_0 | C_0 | C_1 | C_1 | C_1 | C_1 |
| B   | B_0 | B_0 | B_1 | B_1 | B_0 | B_0 | B_1 | B_1 |
| A   | A_0 | A_1 | A_0 | A_1 | A_0 | A_1 | A_0 | A_1 |
| J_0 | 0.9 | 0.3 | 0.9 | 0.3 | 0.8 | 0.8 | 0.4 | 0.4 |
| J_1 | 0.1 | 0.7 | 0.1 | 0.7 | 0.2 | 0.2 | 0.6 | 0.6 |
然后应该有一种方法来切换表内的元组(例如,如果用户希望在表内切换
B
a
,使得
B
是变化最快的值)

请记住,这些值也会相应地发生变化。在表中切换
A
B
之后,它应该是这样的

| C   | C_0 | C_0 | C_0 | C_0 | C_1 | C_1 | C_1 | C_1 |
| A   | A_0 | A_0 | A_1 | A_1 | A_0 | A_0 | A_1 | A_1 |
| B   | B_0 | B_1 | B_0 | B_1 | B_0 | B_1 | B_0 | B_1 |
| J_0 | 0.9 | 0.9 | 0.3 | 0.3 | 0.8 | 0.4 | 0.8 | 0.4 |
| J_1 | 0.1 | 0.1 | 0.7 | 0.7 | 0.2 | 0.6 | 0.2 | 0.6 |
因此,问题归结为:

根据标题的新顺序查找新值,其中 标题可以有不同的基数(它可以包含的值的数量) 采取行动)

为此,我写了下面的方法来完成这项工作,但我不认为它是优雅的或是pythonic的。该方法目前只针对一行编写,可以很容易地扩展到上面给出的多个列表的示例中

def change_order(new_order, old_order, old_card, old_list):
    if (set(new_order) - set(old_order)) or (set(old_order) - set(new_order)):
            raise ValueError("New order either has missing or extra arguments")
    else:
            res = [-1]*len(old_list)
            for i in range(len(old_list)):
                    d = {}
                    idx = i
                    for card, var in zip(old_card, old_order):
                            #prod *= card
                            d[var] = idx%card,card
                            idx //= card
                    new_index = 0

                    prod = 1
                    for var in new_order:
                            new_index += d[var][0]*prod
                            prod *= d[var][1]
                    res[new_index] = old_list[i]


            return res



old_order = ['A','B','C']
old_card = [2,2,2]
new_order = ['B', 'A','C']
old_list = [0.9,0.3,0.9,0.3,0.8,0.8,0.4,0.4]

print(change_order(new_order, old_order, old_card, old_list))
[0.9, 0.9, 0.3, 0.3, 0.8, 0.4, 0.8, 0.4]
我实现的背后的想法可以从任何基中的数字(整个列表被视为一个数字)表示中获取。所以基本上我只是在重新安排新号码中的位置。这只是为了直观地理解上面的代码。这一解释非常模糊,不应过于严肃

所以,我想问一下,是否还有其他方法可以做到这一点

我正在考虑使用numpy的整形()方法(列表或numpy数组对我来说都是可以接受的,尽管任何关于哪个选择更快的建议都会有很大帮助)。即使使用重塑,我能想到的最好的方法是在旧排序和新排序之间进行一对一的映射。所以我在谷歌上搜索了一下,我能找到的最接近的答案是和,但这些并不能充分回答我的问题

编辑:

我正在使要求更严格一点。一对一映射是不可接受的。如果在numpy或python中有一些方法可以通过一次切片多个列来创建新的排序,从而对其进行整齐的重新排序,那就更好了


注:我已经找到了一种我认为符合要求的方法,它简短、清晰,并且使用了已经可用的方法来完成这项工作,我在下面添加了它作为答案。

我在另一个SO问题中找到了一种方法来完成这项工作,我不会删除它,因为找到另一种方法可能有点困难,在我的情况下需要一些小技巧。如果我们提供了新的排序,转置方法本身就会这样做。 以下是根据链接的简短实现:

def change_order2(new_order, old_order, old_card, old_list):
    import numpy as np
    new_ord = [~old_order.index(letter) for letter in new_order]     
    old_list = np.array(old_list).reshape(old_card[::-1])
    new_list = np.transpose(old_list, new_ord[::-1]).flatten()
    return new_list

如果这是您认为可以改进的工作代码,请参阅。如果没有,请澄清问题。是的,这是一个工作代码,但我想要一个完全不同的方法。我提到这一点只是为了说明我所做的尝试。我真的不想对我所采取的方法发表评论。那么这个问题太宽泛了。@jonrsharpe我在这里相对较新,但我不认为这个问题太宽泛。这是一个编程问题,专门询问如何根据上述约束重新排列元素。它可能是广义的,因为它有许多不同的可能答案,但问题本身是具体的。如果有其他更适合的论坛,请提出建议。感谢并原谅我的无知。“这可能是广义的,因为它有许多不同的可能答案”-是的,正是这种意义。“如果有其他更适合的论坛,请建议”-这不是互联网其他部分的清算所。