2014-10-25 6 views
1

Могу ли я объединить ввод и включение в одном утверждении?Смешивание in-in и if-let in Swift

for item in array { 
     if let f = item as? NSDictionary { 
      result.addObject(newFile(f)) 
     } 
    } 

array производится в формате JSON, поэтому я не знаю, если каждый элемент является NSDictionary или нет. Я должен проверить.

Я искал что-то вроде этого:

for item as? NSDictionary in array { 
// code 
} 

Как Python или Ruby.

+2

За что? сделать его короче? ваш код ясен и читаем. Не делайте жизнь сложнее для другого разработчика после того, как вы попытаетесь понять свою логику :) –

+0

Если этот массив представляет собой массив словарей, зачем вам это нужно, если его вообще разрешить? –

+0

Что вы пытаетесь проверить? Какой тип 'array'? –

ответ

3

@nickfalk находится на правильном пути, но мы можем сделать лучше. Его результат, к сожалению, возвращает [AnyObject], который вы не можете затем позвонить newFile с (я предполагаю). Но это нормально, мы можем доиграть до конца Легко.

Что вы хотите, это частичная карта. То есть вы хотите сопоставить некоторые (но, возможно, не все) элементы одного lis t в другой список (от AnyObject до File, если можно). Поэтому должно быть какое-то правило для выбора, а также некоторое правило для сопоставления. Необязательно, давайте объединим их. Назовем функцию, которая делает это f. Тогда его тип:

f: T->U? 

Так что есть какая-то магия функция, которая, возможно, преобразовать T в U. Мы хотим с этим сопоставить. Звучит просто:

extension Array { 
    func partialMap<U>(f: T->U?) -> [U] { 
    var result = [U]() 
    for x in self { 
     if let u = f(x) { 
     result.append(u) 
     } 
    } 
    return result 
    } 
} 

Так что теперь мы скрыли все гадкое мутации и var и этажерки глубоко, где мы не должны смотреть на него. У нас есть функция, которая принимает функцию отображения из «что-то» в «возможно что-то другое» и возвращает список «что-то, что мы могли бы отобразить».

Теперь все красиво и неизменны и многоразовые:

let result = array.partialMap { ($0 as? NSDictionary).map(newFile) } 

Вау там. Что это такое map посередине? Хорошо, as? возвращает NSDictionary?.Если у вас map необязательный, то, если необязательно None, он возвращает None, в противном случае он применяет функцию к значению и обертывает ее в Some. Так что все это занимает AnyObject и возвращает File? так, как мы и хотели. Один partialMap позже у нас есть наш ответ.

+0

Было бы неплохо не возвращать необязательные и отфильтровывать все несовместимые типы в расширении массива. Затем я могу безопасно называть 'newFile', не распаковывая в нем аргумент. – Mohsen

+0

Вот что это делает. 'newFile' вызывается с' NSDictionary', а не опционально. 'partialMap' возвращает' [U] ', а не' [U?] 'или' [U]? '. Если вы хотите превратить 'mapPartial' в' filter-things-I-can-convert', то это просто 'array.partialMap {$ 0 as? NSDictionary} ', который возвращает' [NSDictionary] '. –

+0

Значит, вы также можете использовать 'array.partialMap {$ 0 as? NSDictionary} .map (newFilter) ', но для этого вам потребуется дважды пройти список. Неважно, если он сделает код более понятным для вас (и для длинных цепей он может), но вы также можете сделать это за один проход. –

1

Если ваша цель - уменьшить NSArray до массива, содержащего только фильтр NSDictionary, это очень мощный инструмент. Создайте соответствующую функцию фильтрации:

func filterForNSDictionary(object: AnyObject) -> Bool{ 
    return object.isKindOfClass(NSDictionary) 
} 

Тогда просто передать в вас массив и функции для функции filter

let result = filter(array, filterForNSDictionary) 

Как @RobNapier указывает мое решение выше, в конечном итоге с массивом результата имеющего тип [AnyObject], это, конечно же, можно легко исправить:

let result = filter(array, filterForNSDictionary) as [NSDictionary] 

Это может считаться рискованным, если вы вынудите массив неправильного типа. as [NSString] (для instance9, скорее всего, взрывает в лице вниз по линии ...

решения Робы быть чистой удивительной сообразительностью, конечно, и @MattGibson доставки идеальных стенографий, разоблачая меня как абсолютный новичок в этой области.

3

я бы, вероятно, просто пойти на что-то вроде:

let result = array.filter() { $0 is NSDictionary } 

Если вам нужно result быть массивом NSDictionary, вы можете просто бросить его:

let result = array.filter() { $0 is NSDictionary } as [NSDictionary]