У меня есть массив, как показано ниже;
constants = ['(1,2)', '(1,5,1)', '1']
Я хотел бы преобразовать массив как показано ниже;
constants = [(1,2), 1, 2, 3, 4, 5, 1]
Для этого я попробовал несколько операций;
from ast import literal_eval
import numpy as np
constants = literal_eval(str(constants).replace("'",""))
constants = [(np.arange(*i) if len(i)==3 else i) if isinstance(i, tuple) else i for i in constants]
И выход был;
constants = [(1, 2), array([1, 2, 3, 4]), 1]
Так что это не ожидаемый результат, и я застрял на этом этапе. Вопрос в том, как я могу объединить массив с его родительским массивом?
Мне не нужно его преобразовывать. Мне нужно преобразовать кортежи в 3 значения.
np.arange(1,5,1)
не возвращает np.array([1, 2, 3, 4])
?
@taras Да, это так. Но это не моя проблема. Проблема в том, как объединить его с родительским массивом.
Используйте приведенный ниже код, чтобы разрешить синтаксический анализ, описанный выше:
from ast import literal_eval
constants = ['(1,2)', '(1,5,1)', '1']
processed = []
for index, c in enumerate(constants):
parsed = literal_eval(c)
if isinstance(parsed, (tuple, list)) and index != 0:
processed.extend(range(1, max(parsed) + 1))
else:
processed.append(parsed)
print processed # [(1, 2), 1, 2, 3, 4, 5, 1]
TypeError: isinstance ожидает 2 аргумента, получено 3
Результат мне не понравился. Результат должен быть; [(1,2), 1, 2, 3, 4, 5, 1]
@AndriyIvaneyko, а что, если кортеж не является первым элементом списка?
Элемент @taras будет добавлен.
Я собираюсь предположить, что этот вопрос очень буквальный, и что вы всегда хотите изменить это:
constants = ['(a, b)', '(x, y, z)', 'i']
в это:
transformed = [(a,b), x, x+z, x+2*z, ..., y, i]
таким образом, что второй кортеж представляет собой диапазон от x
до y
с шагом z
. Итак, ваш окончательный преобразованный массив - это первый элемент, затем диапазон, определенный вашим вторым элементом, а затем ваш последний элемент. Самый простой способ сделать это - просто пошагово:
constants = ['(a, b)', '(x, y, z)', 'i']
literals = [eval(k) for k in constants] # get rid of the strings
part1 = [literals[0]] # individually make each of the three parts of your list
part2 = [k for k in range(literals[1][0], literals[1][1] + 1, literals[1][2])] # or if you don't need to include y then you could just do range(literals[1])
part3 = [literals[2]]
transformed = part1 + part2 + part3
Предлагаю следующее:
res = []
for cst in constants:
if isinstance(cst,tuple) and (len(cst) == 3):
#add the range to the list
res.extend(range(cst[0],cst[1], cst[2]))
else:
res.append(cst)
res дает желаемый результат. Может быть более элегантный способ решить эту проблему.
Это один из подходов.
Демо:
from ast import literal_eval
constants = ['(1,2)', '(1,5,1)', '1']
res = []
for i in constants:
val = literal_eval(i) #Convert to python object
if isinstance(val, tuple): #Check if element is tuple
if len(val) == 3: #Check if no of elements in tuple == 3
val = list(val)
val[1]+=1
res.extend(range(*val))
continue
res.append(val)
print(res)
Выход:
[(1, 2), 1, 2, 3, 4, 5, 1]
а если массив: constants = ['(1,2)', '(1,5,1)', '1', '(0.1, 0.9, 0.1)']
? Ошибка: объект float нельзя интерпретировать как целое число.
Каков ожидаемый результат ['(1,2)', '(1,5,1)', '1', '(0.1, 0.9, 0.1)']
?
Ожидаемый результат: [(1,2), 1, 2, 3, 4, 5, 1, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
Я решил это; просто замените range(*val)
на np.arange(*val)
.
Да ... я собирался опубликовать это :)
почему не преобразован первый кортеж?