Изменить значение JSON для ключа, который может быть вложен в Swift

Если вы хотите избежать затрат памяти на преобразование в ряд кортежей или другую подобную структуру данных, вы можете использовать структурные массивы numpy.

Фокус в том, чтобы просмотреть исходный массив как структурированный массив где каждый элемент соответствует строке исходного массива. Это не делает копию и довольно эффективно.

В качестве быстрого примера:

import numpy as np

data = np.array([[1, 1, 1, 0, 0, 0],
                 [0, 1, 1, 1, 0, 0],
                 [0, 1, 1, 1, 0, 0],
                 [1, 1, 1, 0, 0, 0],
                 [1, 1, 1, 1, 1, 0]])

ncols = data.shape[1]
dtype = data.dtype.descr * ncols
struct = data.view(dtype)

uniq = np.unique(struct)
uniq = uniq.view(data.dtype).reshape(-1, ncols)
print uniq

Чтобы понять, что происходит, взгляните на посредника Результаты.

. Когда мы рассматриваем вещи как структурированный массив, каждый элемент в массиве представляет собой строку в исходном массиве. (В принципе, это аналогичная структура данных для списка кортежей.)

In [71]: struct
Out[71]:
array([[(1, 1, 1, 0, 0, 0)],
       [(0, 1, 1, 1, 0, 0)],
       [(0, 1, 1, 1, 0, 0)],
       [(1, 1, 1, 0, 0, 0)],
       [(1, 1, 1, 1, 1, 0)]],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])

In [72]: struct[0]
Out[72]:
array([(1, 1, 1, 0, 0, 0)],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])

Как только мы запустим numpy.unique, мы получим структурированный массив назад:

In [73]: np.unique(struct)
Out[73]:
array([(0, 1, 1, 1, 0, 0), (1, 1, 1, 0, 0, 0), (1, 1, 1, 1, 1, 0)],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])

Затем нам нужно посмотреть как «нормальный» массив (_ хранит результат последнего вычисления в ipython, поэтому вы видите _.view...):

In [74]: _.view(data.dtype)
Out[74]: array([0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0])

Затем переформатируйте обратно в 2D-массив (-1 является заполнителем, который говорит numpy, чтобы вычислить правильное количество строк, указать количество столбцов):

In [75]: _.reshape(-1, ncols)
Out[75]:
array([[0, 1, 1, 1, 0, 0],
       [1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0]])

Очевидно, если вы хотели бы быть более кратким, вы могли бы написать его как:

import numpy as np

def unique_rows(data):
    uniq = np.unique(data.view(data.dtype.descr * data.shape[1]))
    return uniq.view(data.dtype).reshape(-1, data.shape[1])

data = np.array([[1, 1, 1, 0, 0, 0],
                 [0, 1, 1, 1, 0, 0],
                 [0, 1, 1, 1, 0, 0],
                 [1, 1, 1, 0, 0, 0],
                 [1, 1, 1, 1, 1, 0]])
print unique_rows(data)

В результате:

[[0 1 1 1 0 0]
 [1 1 1 0 0 0]
 [1 1 1 1 1 0]]
0
задан robertsan 6 March 2019 в 09:59
поделиться

1 ответ

Незнание структуры вашего JSON немного усложняет эту проблему, но ее все же можно решить. У меня возникла идея рекурсивного поиска по словарю

extension Dictionary
{
    mutating func updateValueRecursively(forKey key : Key, newValue: Value) -> Bool
    {
        if keys.contains(key)
        {
            self[key] = newValue
            return true
        }
        for (_, value) in enumerated()
        {
            if var dict = value.value as? Dictionary<Key, Value> {
                if dict.updateValueRecursively(forKey: value.key, newValue: newValue), let newDict = dict as? Value {
                    self[value.key] = newDict
                    return true
                }
            }
        }
        return false
    }
}

Конечно, сначала вам нужно превратить строку JSON в словарь

var dict : Dictionary<String : Any>
if let data = jsonString.data(using: .utf8) {
do {
    dict=  try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
    print(error.localizedDescription)
}
.
0
ответ дан mag_zbc 6 March 2019 в 09:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: