Вы можете использовать dot-notation для доступа и установки полей глубоко внутри объектов, не влияя на другие свойства этих объектов.
Учитывая объект, указанный вами выше:
> db.test.insert({"id": "test_object", "some_key": {"param1": "val1", "param2": "val2", "param3": "val3"}})
WriteResult({ "nInserted" : 1 })
Мы можем обновить только some_key.param2
и some_key.param3
:
> db.test.findAndModify({
... query: {"id": "test_object"},
... update: {"$set": {"some_key.param2": "val2_new", "some_key.param3": "val3_new"}},
... new: true
... })
{
"_id" : ObjectId("56476e04e5f19d86ece5b81d"),
"id" : "test_object",
"some_key" : {
"param1" : "val1",
"param2" : "val2_new",
"param3" : "val3_new"
}
}
Вы можете вникать так глубоко, как вам нравится. Это также полезно для добавления новых свойств к объекту без влияния на существующие.
Вы можете получить довольно хорошее ускорение для второй части проблемы (которую вы делаете посредством поиска по словарю), используя только Numpy. Я заменил поиск по словарю путем индексации в массив Numpy.
Я генерирую массив Numpy в начале. Одна хитрость заключается в том, чтобы понять, что буквы могут быть преобразованы в базовое число, которое представляет их, используя ord
. Для строки ASCII это всегда между 0 и 127:
_base642bin_array = np.zeros((128,),dtype=np.uint8)
for i in range(len(_base64chars)):
_base642bin_array[ord(_base64chars[i])] = i
Я выполняю преобразование в 1 и 0 в функции n_decompress
, используя встроенную функцию numpy.
def n_decompress2(compressed_vector):
# encode is for Python 3: str -> bytes
decompressed_b64 = "".join(_decompress_get(compressed_vector)).encode()
# byte string into the underlying numeric data
decompressed_b64 = np.fromstring(decompressed_b64,dtype=np.uint8)
# conversion done by numpy indexing rather than dictionary lookup
vectorized = _base642bin_array[decompressed_b64]
# convert to a 2D array of 1s and 0s
as_binary = np.unpackbits(vectorized[:,np.newaxis],axis=1)
# remove the two digits you don't care about (always 0) from binary array
as_binary = as_binary[:,2:]
# reshape to 1D (and chop off two at the end)
return as_binary.ravel()[:-2]
Это дает мне 2,4-кратную скорость по сравнению с вашей версией (обратите внимание, что я вообще не изменил _decompress_get
, поэтому оба времени включают в себя ваш _decompress_get
) только от использования Numpy (без Cython / Numba, и Я подозреваю, что они не слишком помогут). Я думаю, что главное преимущество заключается в том, что индексирование в массив с числами происходит быстрее по сравнению с поиском в словаре.
_decompress_get
, вероятно, можно улучшить с помощью Cython, но это значительно сложнее ...