簡體   English   中英

前向填充位數組的最有效方法

[英]Most efficient way to forward fill a bit array

想象一下,您有一個隨機填充的位數組(任何數據類型都可以。例如 list、np.array、bitarray、bitmap 等布爾值)。 在 Python 中“前向填充”(從左到右,或第 0 個索引到第 n 個索引)該數組的最快方法是什么,以便在每個已設置為 1 的位之后將 n 位設置為 1?

例如,取下面的數組:

[01000100000]

給定 n=2 前向填充數組將是:

[01110111000]

編輯
假設輸入是一個包含 10,000 個元素的位數組,其中隨機 20% 為真,n=25。 這可以表示為一個 python 列表,其中包含 10,000 個 boolean 元素,其中 20% 是True 這也可以表示為具有 0 到 10,000 之間的 2,000 個int元素的set

編輯 2
首先,以下是使用上述參數的一些示例:

new = set()
new.update(*[range(i, i+25) for i in existing])
# 2.34 ms ± 56.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
new = BitMap()  # This is a pyroaring BitMap
for e in existing:
    new.add_range(e, e+25)
# 461 µs ± 6.02 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我在下面討論了幾種數據類型。 沒有給定時間,您可能希望將語句設置ans或重構函數的時間設置為對您有意義的粒度。

# -*- coding: utf-8 -*-
"""
Created on Sun Dec 19 09:08:56 2021

for: https://stackoverflow.com/questions/70397220/most-efficient-way-to-forward-fill-a-bit-array

@author: paddy
"""

from random import sample


n = 2  # bits to the right of set bits to also set 
elements = 17
true_percent = 20.0


#%% Using arbitrary precision int
print("\nUsing arbitrary precision int.\n".upper())
from operator import or_
from functools import reduce


# Set some random bits True
bits = sum(1 << r 
           for r in sample(range(elements), int(true_percent/100 * elements)))

# Set n right-adjacent bits.
ans = reduce(or_, (bits >> x for x in range(n+1)), 0)

# Print
print(f"Random bits = {bits:0{elements}b}")
if 1: 
    print()
    for x in range(n+1):
        print(f"              {bits >> x:0{elements}b}")
    print()
print(f"Answer      = {ans:0{elements}b}\n")


#%% Using list.
print("\nUsing list.\n".upper())
from operator import or_
from functools import reduce


bits = [0] * elements
# Set some random bits to 1
for r in sample(range(elements), int(true_percent/100 * elements)):
    bits[r] = 1

# Set n right-adjacent bits.
#   [0]*x is padding bits on the left.
#   zip(*(list1, list2,..)) returns the n'th elements on list1, list2,...
#   int(any(...)) or's them.
ans = [int(any(shifts)) 
       for shifts in zip(*([0]*x + bits for x in range(n+1)))]

# Print
print(f"Random bits = {bits}")
if 1: 
    print()
    for x in range(n+1):
        print(f"              {[0]*x + bits}")
    print()
print(f"Answer      = {ans}\n")


#%% Using numpy.

# Adapt the list solution to use numpy operators on numpy arrays


#%% Using other ordered collections such as str.

# Convert to and from int solution.

樣品 Output:

USING ARBITRARY PRECISION INT.

Random bits = 01000000010000010

              01000000010000010
              00100000001000001
              00010000000100000

Answer      = 01110000011100011


USING LIST.

Random bits = [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]

              [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]
              [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]
              [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]

Answer      = [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM