#arrays #swift #multidimensional-array #swift3 #xcode8
#массивы #swift #многомерный массив #swift3 #xcode8
Вопрос:
Я часами ломал голову и чувствую, что перепробовал большинство вещей, поэтому я обращаюсь к надежному Stack Overflow!
У меня есть массив массивов, поступающих с сервера, который соотносится с меткой времени Unix и значением, которое выглядит следующим образом:
[[1475511843000,183649999],[1475512143000,183612691],[1475512443000,183503638]]
Раньше я просто устанавливал эту переменную как var graphPoints:NSArray = []
Сейчас я пытаюсь преобразовать в Swift3 и использовать [[UInt32:Int]]()
, чтобы указать, что у меня есть массив, содержащий другие массивы, которые имеют 32 целых числа без знака, а также целое число впоследствии. Независимо от того, какой способ я пробовал, включая стандартный или подслащенный синтаксис:
[Int:[UInt32:Int]]()
[[UInt32:Int]]()
[[]]()
позволяет мне получить доступ ко второму массиву из-за проблемы с вводом, обычно выдает ошибку, похожую на Type 'Int?' has no subscript members
.
Данные были в этом формате до того, как я высказался о том, как они будут отформатированы, поэтому я не могу это настроить, любая помощь была бы очень признательна.
Вызов сервера выглядит следующим образом: `Alamofire.request(urlString).responseJSON { ответ в ответе коммутатора.результат { case .success(пусть данные): пусть json = JSON(данные);
//print("GRAPH DATA POINTS JSON: (json)")
//some graphs don't contain data so we have to test for null
if !json.isEmpty {
self.graphPoints = json["data"].arrayObject! as! [(timestamp: UInt64, value: Int)]
if self.graphPoints.count > 0 {
self.firstPriceInGraph = self.graphPoints[0][0].doubleValue
self.setupPercentageLabel()
} else {
//no graph data available, hide something?
self.firstPriceInGraph = -1.0
if Helper.__DEBUG { print("NO DATA IN JSON... 1")}
}
} else {
//no graph data available, hide something?
self.firstPriceInGraph = -1.0
if Helper.__DEBUG {print("NO DATA IN JSON... 2")}
}
self.graphView.reloadData()
case .failure(let error):
self.graphPoints = [(timestamp:UInt64, value:Int)]()
self.graphView.reloadData()
print("Get Graph Data - Request failed with error: (error)")
}
}`
Комментарии:
1. У вас есть массив массива, и в первых двух объявлениях вы указываете, что это массив словаря, попробуйте один раз
[[UInt32]]
2. @NiravD 1475511843000 не подходит
UInt32
.UInt64
здесь лучший выбор.3. Похоже, OP просто хочет, чтобы старый код Swift 2.2 отлично работал с Swift 3.0 🙂 К сожалению, иногда это невозможно.
4. @StuartP. это имеет смысл. Смотрите мой обновленный ответ.
5. На самом деле, я не думаю, что это помогает. Существует проблема с
graphPoints
иfirstPriceInGraph
: у них неправильные типы
Ответ №1:
Как вы и сказали, это Array
из других Array
s. [[UInt32:Int]]()
вместо этого создал бы Array
Dictionary
значение s, потому [UInt32:Int]
что это a Dictionary
с UInt32
ключами as и Int
значениями as.
Массивы Swift содержат только один тип элемента, поэтому вы можете сделать [[Integer]]
, Integer
будучи протоколом, которому UInt32
Int
соответствуют оба и. Затем при доступе вам пришлось бы явно приводить к либо UInt32
или Int
, если вы хотите, чтобы они были в этих типах.
Вы также можете затем преобразовать это [[Integer]]
в a [(UInt32, Int)]
, an Array
из кортежей, содержащих a UInt32
и an Int
.
Ответ №2:
Сейчас я пытаюсь преобразовать в Swift 3 и использовать
[[UInt32:Int]]()
, чтобы указать, что у меня есть массив, содержащий другие массивы, которые имеют 32 целых числа без знака, а также целое число после этого.
Это совсем не то, что это значит. [[UInt32: Int]]()
является сокращением для: Array<Dictionary<UInt32, Int>>.init()
Единственный способ получить массив из 2 типов, таких как UInt32
и Int
, — это сохранить в массиве супертип обоих этих типов. В этом случае, UInt32
и Int
оба имеют общее соответствие Integer
протоколу, поэтому вы можете хранить оба UInt32
и Int
в Array<Integer>
. Однако это довольно грубо, поскольку для этого вам потребуется постоянно явно выполнять приведение из Integer
в UInt32
или Int
. Косвенность, которую это вводит, также приводит к снижению производительности.
Лучший способ добиться аналогичного результата — хранить кортежи UInt32 и Int:
let graphPoints: [(UInt32, Int)] = [
(1475511843000, 183649999),
(1475512143000, 183612691),
(1475512443000, 183503638)
]
Однако это даже не работает, потому 1475511843000
что слишком велико для остановки в a UInt32
, максимальное значение которого равно 4294967295
( UInt32.max
) .
Ответ №3:
То, что вы написали, является словарем, а не многомерным массивом.
[[UInt32:Int]]()
создает массив словарей, который имеет UInt32
как ключи, Int
так и значения.
[Int:[UInt32:Int]]()
создает словарь, который использует Int
в качестве ключей и другого типа словаря в качестве значений.
Оба вышеперечисленных не то, что вы хотите.
Поскольку ваши данные представляют UInt32
Int
собой пары, вам, вероятно, не следует использовать многомерный массив для их хранения, поскольку массив может хранить только один тип значения.
Мое предложение — использовать массив кортежей:
[(UInt32, Int)]
Пример использования:
theArray[3].0 // get the timestamp of the fourth item
theArray[7].1 // get the Int value of the eighth item
В качестве альтернативы попробуйте использовать словарь:
[UInt32: Int]
Обратите внимание, что это делает данные неупорядоченными. Вы можете получить доступ к значениям только с помощью ключей.
Комментарии:
1. Похоже, это приводит к тому
Cannot subscript a value of type 'inout [(timestamp: UInt64, value: Int)]' (aka 'inout Array<(timestamp: UInt64, value: Int)>')
, что при попытке получить доступ к данным следующим образомlet timestamp = self.graphPoints[0].timestamp
2. @StuartP. Кажется, я не могу воспроизвести это. Можете ли вы отредактировать свой вопрос, чтобы показать больше кода?
Ответ №4:
Как насчет этого:
let array = [[UInt64]]()
или
let array: [[UInt64]] = [[1475511843000,183649999],[1475512143000,183612691],[1475512443000,183503638]]
То, что вы пытаетесь определить с помощью [Int:[UInt32:Int]]()
and [[UInt32:Int]]()
, не является массивом массивов. Первый — это словарь, где значение — это другой словарь. Второй — это массив словарей.
PS: Как упоминал Александр Момчилов, лучше обернуть ваши данные в [(UInt64, Int)]
Комментарии:
1.
Type 'UInt64' has no subscript members
это результат, но я попытаюсь обернуть данные, каков наилучший способ извлечь данные из этого, поскольку я полагаю, что это не будет, например, через [0] [0] . Также я считаю, что типы данных должны быть частью этого сейчас, так что, возможно[(timestamp:UInt64, value:Int)]
2.
Type 'UInt64' has no subscript members
является результатом чего?3.
let array = [[UInt64]]()
Когда я пытаюсь получить к нему доступ черезlet value = self.graphPoints[0][0]
4. @StuartP. Что это за тип
self.graphPoints
? Вы заменилиNSArray
на[[UInt64]]
?let value = array[0][0]
для меня работает просто отлично. ВОЗВРАТ1475511843000