Per спецификация W3C HTML5 :
^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
Контекст:
Действительный адрес электронной почты - это строка, которая соответствует ABNF production [...].
Примечание. Это требование является преднамеренным нарушением в RFC 5322 , который определяет синтаксис адресов электронной почты, который является одновременно слишком строгий (до символа «@»), слишком неопределенный (после символа «@») и слишком слабый (позволяющий использовать комментарии, пробельные символы и кавычки в манерах, незнакомых большинству пользователей).
Следующее регулярное выражение, совместимое с JavaScript и Perl, является реализацией указанного выше определения.
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
Для полноты в numpy> = 1.8 вы также можете использовать метод np.add
at
:
In [8]: m, n = np.random.rand(2, 10)
In [9]: m_idx, n_idx = np.random.randint(10, size=(2, 20))
In [10]: m0 = m.copy()
In [11]: np.add.at(m, m_idx, n[n_idx])
In [13]: m0 += np.bincount(m_idx, weights=n[n_idx], minlength=len(m))
In [14]: np.allclose(m, m0)
Out[14]: True
In [15]: %timeit np.add.at(m, m_idx, n[n_idx])
100000 loops, best of 3: 9.49 us per loop
In [16]: %timeit np.bincount(m_idx, weights=n[n_idx], minlength=len(m))
1000000 loops, best of 3: 1.54 us per loop
. Помимо очевидного недостатка производительности, он имеет несколько преимуществ:
np.bincount
преобразует его веса в плавающие значения с двойной точностью, .at
будет работать с вашим родным типом массива. Это делает его самым простым вариантом для решения, например. с комплексными числами. np.bincount
только добавляет веса вместе, у вас есть метод at
для всех ufuncs, поэтому вы можете многократно multiply
или logical_and
или что хотите. Но для вашего случая использования np.bincount
, вероятно, способ пойти.
Для наглядности давайте определим
>>> m_ind, n_ind = w.T
Затем цикл for
for i, j in zip(m_ind, n_ind):
M[i] += N[j]
обновляет записи M[np.unique(m_ind)]
. Значения, которые записываются в него, - N[n_ind]
, которые должны быть сгруппированы по m_ind
. (Тот факт, что есть n_ind
в дополнение к m_ind
, фактически тангенциальен для вопроса, вы можете просто установить N = N[n_ind]
.) Существует, по-видимому, класс SciPy, который выполняет именно это: scipy.sparse.csr_matrix
.
Пример данных:
>>> m_ind, n_ind = array([[0, 0, 1, 1], [2, 3, 0, 1]])
>>> M = np.arange(2, 6)
>>> N = np.logspace(2, 5, 4)
Результат цикла for
заключается в том, что M
становится [110002 1103 4 5]
. Мы получаем тот же результат с csr_matrix
следующим образом. Как я уже говорил ранее, n_ind
не имеет значения, поэтому мы избавимся от этого.
>>> N = N[n_ind]
>>> from scipy.sparse import csr_matrix
>>> update = csr_matrix((N, m_ind, [0, len(N)])).toarray()
Конструктор CSR строит матрицу с требуемыми значениями по требуемым индексам; третья часть его аргумента представляет собой индекс сжатого столбца, что означает, что значения N[0:len(N)]
имеют индексы m_ind[0:len(N)]
. Дубликаты суммируются:
>>> update
array([[ 110000., 1100.]])
Это имеет форму (1, len(np.unique(m_ind)))
и может быть добавлено непосредственно:
>>> M[np.unique(m_ind)] += update.ravel()
>>> M
array([110002, 1103, 4, 5])
Используя также m_ind, n_ind = w.T
, просто сделайте M += np.bincount(m_ind, weights=N[n_ind], minlength=len(M))