Я бы не пошел с MSTest. Хотя это, вероятно, самое перспективное доказательство наличия фреймворков с Microsoft, это не самое гибкое решение. Он не будет работать в одиночестве без некоторых хаков. Поэтому запустить его на сервере сборки, отличном от TFS, без установки Visual Studio сложно. Визуальный тестовый прогон на самом деле медленнее, чем Testdriven.Net + любой другой фреймворк. А поскольку выпуски этой среды привязаны к выпускам Visual Studio, обновлений меньше, и если вам приходится работать со старыми VS, вы привязаны к более старому MSTest.
Я не думаю, что это имеет большое значение, какие другие фреймворки вы используете. Это действительно легко переключаться с одного на другой.
Я лично использую XUnit.Net или NUnit в зависимости от предпочтений моих коллег. NUnit является самым стандартным. XUnit.Net является самой простой структурой.
Хотя и не numpy
примитивы, функции itertools
часто бывают очень быстрыми, так что попробуйте эту функцию (и измерьте время для различных решений, включая это один, конечно):
def runs_of_ones(bits):
for bit, group in itertools.groupby(bits):
if bit: yield sum(group)
Если вам действительно нужны значения в списке, конечно, вы можете просто использовать list (run_of_ones (bits)); но, возможно, понимание списка может быть еще немного быстрее:
def runs_of_ones_list(bits):
return [sum(g) for b, g in itertools.groupby(bits) if b]
Переходя к «естественным для numpy» возможностям, как насчет:
def runs_of_ones_array(bits):
# make sure all runs of ones are well-bounded
bounded = numpy.hstack(([0], bits, [0]))
# get 1 at run starts and -1 at run ends
difs = numpy.diff(bounded)
run_starts, = numpy.where(difs > 0)
run_ends, = numpy.where(difs < 0)
return run_ends - run_starts
Опять же: не забудьте сравнить решения друг с другом на реалистичных для вас примерах!
Here is a solution using only arrays: it takes an array containing a sequence of bools and counts the length of the transitions.
>>> from numpy import array, arange
>>> b = array([0,0,0,1,1,1,0,0,0,1,1,1,1,0,0], dtype=bool)
>>> sw = (b[:-1] ^ b[1:]); print sw
[False False True False False True False False True False False False
True False]
>>> isw = arange(len(sw))[sw]; print isw
[ 2 5 8 12]
>>> lens = isw[1::2] - isw[::2]; print lens
[3 4]
sw
contains a true where there is a switch, isw
converts them in indexes. The items of isw are then subtracted pairwise in lens
.
Notice that if the sequence started with an 1 it would count the length of the 0s sequences: this can be fixed in the indexing to compute lens. Also, I have not tested corner cases such sequences of length 1.
Full function that returns start positions and lengths of all True
-subarrays.
import numpy as np
def count_adjacent_true(arr):
assert len(arr.shape) == 1
assert arr.dtype == np.bool
if arr.size == 0:
return np.empty(0, dtype=int), np.empty(0, dtype=int)
sw = np.insert(arr[1:] ^ arr[:-1], [0, arr.shape[0]-1], values=True)
swi = np.arange(sw.shape[0])[sw]
offset = 0 if arr[0] else 1
lengths = swi[offset+1::2] - swi[offset:-1:2]
return swi[offset:-1:2], lengths
Tested for different bool 1D-arrays (empty array; single/multiple elements; even/odd lengths; started with True
/False
; with only True
/False
elements).
Просто в случае, если кому-то интересно (и поскольку вы упомянули MATLAB мимоходом), вот один из способов решить эту проблему в MATLAB:
threshold = 7;
d = 10*rand(1,100000); % Sample data
b = diff([false (d < threshold) false]);
durations = find(b == -1)-find(b == 1);
Я не слишком хорошо знаком с Python, но, возможно, это может помочь вам дать некоторые идеи. =)
durations = []
counter = 0
for bool in b:
if bool:
counter += 1
elif counter > 0:
durations.append(counter)
counter = 0
if counter > 0:
durations.append(counter)