2015-02-03 4 views
2

x - объект, который содержит массив, называемый точкой.Как назначить срез чисел массиву в swift

x выполняет оператор индекса, так что вы можете делать такие вещи, как x[i], чтобы получить i-й элемент массива (типа T, который обычно является Int или Double).

Это то, что я хочу сделать:

x[0...2] = [0...2] 

Но я получаю сообщение об ошибке: ClosedInterval<T> не конвертируется в Int/Double.

Edit1:

Вот мой объект x:

let x = Point<Double>(dimensions:3) 

Для пинков и хихиканья: определить x, как [1.0,2.0,0.0]

я могу получить первые n элементы через x[0...2].

Я хочу знать, как обновить x [0 ... 2], чтобы удерживать [0.0, 0.0.0.0] одним махом. Интуитивно, я хотел бы сделать x[0...2] = [0...2]. Это не работает, как можно видеть в ответах. Я хочу обновить x без итераций (на моем конце) и скрыть тот факт, что x не является массивом (хотя это не так).

+0

Пытались ли вы функцию карты, или вариант над ним? – holroy

ответ

0

Вам необходимо реализовать subscript(InvervalType), чтобы обрабатывать случай нескольких назначений, подобных этому. Это не делается автоматически.

+0

Можете ли вы сказать больше? Я выполнил поиск в Google для индекса (InvervalType) и ничего не нашел. – user678392

4

[0...2] представляет собой массив с одним элементом, который, в лучшем случае, будет Range<Int> от 0 до 2. Вы не можете назначить, что срез, содержащий, скажем, Int с.

x[0...2] С другой стороны, это (возможно) срез, а Sliceable определяет только индекс get, а не сеттер. Таким образом, даже если типы были более совместимы, то есть, если вы пробовали x[0...2] = 0...2, который, по крайней мере, пытается заменить диапазон в пределах x со значениями аналогичной коллекции - он все равно не сработает.

редактировать: в @rintaro указывает, массив поддерживает сеттер индекс для диапазонов - так что если x были диапазон вы могли бы сделать x[0...2] = Slice(0...2) - но он должен быть кусочек вы назначаете, так что я бы еще пойти с replaceRange ,

Если то, что вы имеете в виду вы хотите заменить 0 записей через 2 с некоторыми значениями, что вы хотите replaceRange, до тех пор, как ваша коллекция соответствует RangeReplaceableCollection (который, например, Array делает):

var x = [0,1,2,3,4,5] 
var y = [200,300,400] 
x.replaceRange(2..<5, with: y) 
// x is now [0,1,200,300,400,5] 

Примечание. Заменяемый диапазон и y не должны быть одинакового размера, коллекция будет расширяться/сокращаться по мере необходимости.

Кроме того, y не имеет никакого массива, это может быть любая коллекция (должна быть коллекция, хотя и не последовательность).Таким образом, приведенный выше код может быть написан как:

var x = [0,1,2,3,4,5] 
var y = lazy(2...4).map { $0 * 100 } 
x.replaceRange(2..<5, with: y) 

редактирования: так, за ваши изменения, чтобы в месте обнулить массив любого размера в один раз, вы можете сделать:

var x = [1.0,2.0,0.0] 
// range to replace is the whole array's range, 
// Repeat just generates any given value n times 
x.replaceRange(indices(x), with: Repeat(count: x.count, repeatedValue: 0.0)) 

Соответственно отрегулируйте диапазон (и количество замещающих записей), если вы хотите просто выровнять поддиапазон.

Учитывая свой класс пример Point, вот как вы могли бы реализовать такое поведение, предполагая, что это опирается на массив под капотом:

struct Point<T: FloatLiteralConvertible> { 
    private var _vals: [T] 

    init(dimensions: Int) { 
     _vals = Array(count: dimensions, repeatedValue: 0.0) 
    } 

    mutating func replaceRange 
     <C : CollectionType where C.Generator.Element == T> 
     (subRange: Range<Array<T>.Index>, with newElements: C) { 

     // just forwarding on the request - you could perhaps 
     // do some additional validation first to ensure dimensions 
     // aren't being altered... 
     _vals.replaceRange(subRange, with: newElements) 

    } 

} 

var x = Point<Double>(dimensions:3) 
x.replaceRange(0...2, with: [1.1,2.2,3.3]) 
+0

x не массив. Я надеялся рассматривать его как один (n-dim Point). Он содержит массив. – user678392

+0

Уверен, но вам все равно нужен эквивалент 'replaceRange' - вы можете перенаправить реализацию на содержащийся объект. –

+1

@AirspeedVelocity FWIW, 'Array' реализует сеттер для среза. В вашем последнем примере '_vals [subRange] = Slice (newElements)' должен работать. – rintaro

Смежные вопросы