改变具有奇数索引和的元素的符号

Posted

技术标签:

【中文标题】改变具有奇数索引和的元素的符号【英文标题】:Change sign of elements with an odd sum of indices 【发布时间】:2018-08-19 20:37:00 【问题描述】:

arr 是一个 n 维 numpy 数组。

如何用奇数个索引改变 arr 的每个元素的符号?

例如,arr[0, 1, 2] 需要更改符号,因为它有一个索引总和 0 + 1 + 2 = 3,这是奇数。

当我将arr 转换为一个列表时,我注意到列表中的每个第二个元素都是需要更改符号的元素。

另一个例子:

Original array:

[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]]

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]

Array with signs changed:
[[[ 0  -1  2]
  [ -3  4  -5]
  [ 6  -7  8]]

 [[ -9 10 -11]
  [12 -13 14]
  [-15 16 -17]]

 [[18 -19 20]
  [-21 22 -23]
  [24 -25 26]]]

【问题讨论】:

很不清楚你在问什么。请澄清。 欢迎来到 SO。请提供 minimal reproducible example 你的意思是你想将每个元素乘以 -1 或 +1,+-1 形成一个像棋盘一样的矩阵? 矩阵 a=i,j [1,2,3, 4,5,6, 7,8,9] 例如 a[0][0]=1 a[1][2 ]=6 如果索引的总和是奇数,你必须将它乘以 -1,所以 a[0][0]=1 将是 -1 而 a[1][2]=6 将是 -6 审稿人请注意这个问题已经被一位乐于助人的编辑澄清了。 【参考方案1】:

np.negative 比乘法快一点(因为它是 ufunc

N = 5
arr = np.arange(N ** 3).reshape(N, N, N)
%timeit arr.ravel()[1::2] *= -1
%timeit np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2])

The slowest run took 8.74 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 3.39 µs per loop
The slowest run took 5.57 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 3.12 µs per loop

N = 25
arr = np.arange(N ** 3).reshape(N, N, N)
%timeit arr.ravel()[1::2] *= -1
%timeit np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2])

The slowest run took 7.03 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 10.8 µs per loop
The slowest run took 5.27 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 8.63 µs per loop

N = 101
arr = np.arange(N ** 3).reshape(N, N, N)
%timeit arr.ravel()[1::2] *= -1
%timeit np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2])

1000 loops, best of 3: 663 µs per loop
1000 loops, best of 3: 512 µs per loop

【讨论】:

【参考方案2】:

hpaulj 的建议大大简化了。

程序:

import numpy as np


def change_sign(arr):
    """Switch sign of every second element of arr in-place
    Note
    ----
    Modifies the input array (arr).
    """
    # arr.reshape(-1) makes a 1D view of arr
    #
    # [1::2] select every other element of arr,
    #   starting from the 1st element.
    #
    # *= -1 changes sign of selected elements.

    arr.reshape(-1)[1::2] *= -1
    return arr


def main():
    N = 3
    arr = np.arange(N ** 3).reshape(N, N, N)
    print("original array:")
    print(arr)
    print("change signs")
    print(change_sign(arr))


main()

结果:

original array:
[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]]

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]
change signs
[[[  0  -1   2]
  [ -3   4  -5]
  [  6  -7   8]]

 [[ -9  10 -11]
  [ 12 -13  14]
  [-15  16 -17]]

 [[ 18 -19  20]
  [-21  22 -23]
  [ 24 -25  26]]]

【讨论】:

arr.ravel()[1::2]*=-1 怎么样?否定展平视图中的所有其他元素。 @hpaulj 简单多了哈哈。 甚至np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2]) 可能更快,但可读性稍差

以上是关于改变具有奇数索引和的元素的符号的主要内容,如果未能解决你的问题,请参考以下文章

对向量中具有奇数索引的数字进行排序

在C中将奇数索引元素从一个数组复制到另一个数组

26 计算用户输入的内容中索引为奇数并且对应的元素为数字的个数的两种方法

具有开始和结束索引的最大子数组

jquery 获取奇数索引的元素

匹配所有索引值为偶数/奇数的元素,从 0 开始计数