2015-12-16 1 views
7

У меня есть эти строки кода в Swift:Можно использовать концепцию уменьшения массива от быстрой в объективе c?

let graphPoints:[Int] = [4, 2, 6, 4, 5, 8, 3] 

let average = graphPoints.reduce(0, combine: +)/graphPoints.count 

можно «перевести» эти строки кода в Objective C код?

Это не очень ясно для меня, как работает концепция комбинированного комбинирования. Я читал об этом, но все еще неясно.

Я взял код из этого учебника: http://www.raywenderlich.com/90693/modern-core-graphics-with-swift-part-2

Пожалуйста, помогите. Благодарю.

+0

какого типа делает 'graphPoints' массив содержат? –

+1

Угадайте: 'average = [graphView.graphPoints valueForKeyPath: @" @ sum.self "]' (или, может быть, '@ avg' вместо' @ sum'). – Larme

+0

array is: var graphPoints: [Int] = [4, 2, 6, 4, 5, 8, 3] содержит объекты int. – Adela

ответ

7

скажем, у вас есть несколько NSNumber сек, хранящихся в NSArray, вы можете использовать этот оператор коллекции KVC:

NSArray *someNumbers = @[@0, @1.1, @2, @3.4, @5, @6.7]; 
NSNumber *average = [someNumbers valueForKeyPath:@"@avg.self"]; 
+0

Спасибо. Это работает. :) – Adela

+0

вы полностью приветствуетесь :) –

1

reduce функция не является стандартной в Objective-C. Однако вы можете реализовать его как расширение NSArray.

В вашем случае у вас есть массив Int в Swift. Вы не можете иметь это в Objective-C, вам нужен массив NSNumber.

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

@implementation NSArray (Helpers) 

- (NSInteger)reduceInt:(NSInteger)initial combine:(NSInteger (^)(NSInteger acum, NSInteger element))block { 
    if (!self) { 
     return initial; 
    } 

    NSInteger acum = initial; 
    for (id element in self) { 
     if ([element isKindOfClass:[NSNumber class]]) { 
      acum = block(acum, [(NSNumber *)element integerValue]); 
     } 
    } 

    return acum; 
} 

@end 

Вы можете использовать его, то с массивом, что-то вроде этого:

NSArray *a = @[@1, @2, @3]; 
NSInteger result = [a reduceInt:0 combine:^NSInteger(NSInteger acum, NSInteger element) { 
    return acum + element; 
}]; 
+0

Я думаю, что 'reduce' не имеет большого смысла без генерических типов. – Sulthan

+0

@Sulthan Ну, вы можете иметь реализацию' reduce' с ' id's, что достаточно общего для использования в вашем коде. Конечно, наличие дженериков было бы лучше. –

0

как перевести свести к ObjC (или лучше сказать, как решить вашу «среднюю проблему» в Objective C) был отлично ответил Андре Слотта. быстрое сокращение намного больше. Я постараюсь ответить на вторую часть вашего вопроса, как эта концепция работает в быстром

func reduce<T>(initial: T, @noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> T 

возвращает результат многократного вызова в сочетании с накопленным значением инициализируется начальными и каждый элементом себя, в поворот, т. е. возврат комбинат (комбинация (комбинация (комбинация (начальная, self [0]), self [1]), ... self [count-2]), self [count-1]).

let arr: Array<Int> = [1,2,3,4,5] 
let sum = arr.reduce(0) { (sum, i) -> Int in 
    return sum + i 
} 
print(sum) // 15 

// this is an quasi equivalent of 
var sum1 = 0 // ..... reduce(0).... 
arr.forEach { (elementValue) -> Void in 
    sum1 = sum1 + elementValue // ...{ return sum + i } 
} 
print(sum1) // 15 reduce function will return accumulated inital value 

// reduce is part of SequenceType protocol, that is why 

let arr1 = ["H","e","l","l","o"," ","w","o","r","l","d"] 
let str = arr1.reduce("") { (str, s) -> String in 
    str + s 
} 
// works the same way 
print(str) // "Hello world" 

// let have a litle bit more complex example, to see how powerful, useful and easy to use reduce can be 
let dict = arr1.reduce([:]) { (var dict, s) -> Dictionary<Int,String> in 
    let i = dict.count 
    dict.updateValue(s, forKey: i+1) 
    return dict 
} 
print(dict) // [11: "d", 10: "l", 2: "e", 4: "l", 9: "r", 5: "o", 6: " ", 7: "w", 3: "l", 1: "H", 8: "o"] 
0

написать расширение NSArray

- (NSInteger)reduceStart:(NSInteger)start combine:(NSInteger(^)(NSInteger x, NSInteger y))combine { 
    for (NSNumber* n in self) { 
     if ([n isKindOfClass:[NSNumber class]]) { 
      start = combine (start, n.integerValue); 
     } 
    } 
    return start; 
} 

исправить все ошибки, которые я сделал, и это все. Только менее гибкий, чем Swift.

0

для Objective-C, я хотел бы добавить высшие порядки-функции в этот список ответов: https://github.com/fanpyi/Higher-Order-Functions

#import <Foundation/Foundation.h> 
typedef id (^ReduceBlock)(id accumulator,id item); 
@interface NSArray (HigherOrderFunctions) 
-(id)reduce:(id)initial combine:(ReduceBlock)combine; 
@end 

#import "NSArray+HigherOrderFunctions.h" 
@implementation NSArray (HigherOrderFunctions) 
-(id)reduce:(id)initial combine:(ReduceBlock)combine{ 
    id accumulator = initial; 
    for (id item in self) { 
     accumulator = combine(accumulator, item); 
    } 
    return accumulator; 
} 
@end 

пример:

NSArray *numbers = @[@5,@7,@3,@8]; 
    NSNumber *sum = [numbers reduce:@0 combine:^id(id accumulator, id item) { 
     return @([item intValue] + [accumulator intValue]); 
    }]; 
    NSNumber *multiplier = [numbers reduce:@1 combine:^id(id accumulator, id item) { 
     return @([item intValue] * [accumulator intValue]); 
    }]; 
    NSLog(@"sum=%@,multiplier=%@",sum,multiplier); 
Смежные вопросы