可以在目标c中使用swift中的数组简化概念吗?

时间:2023-01-15 18:33:51

I have this lines of code in Swift:

我在Swift中有这行代码:

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

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

It is possible to "translate" this lines of code in objective c code?

可以在目标c代码中“翻译”这行代码吗?

It's not very clear for me how reduce combine concept works. I read about it but still is unclear.

对于我来说,减少结合概念的作用并不是很清楚。我读过它但仍不清楚。

I took the code from this tutorial: http://www.raywenderlich.com/90693/modern-core-graphics-with-swift-part-2

我从本教程中获取了代码:http://www.raywenderlich.com/90693/modern-core-graphics-with-swift-part-2

Please help. Thanks.

请帮忙。谢谢。

5 个解决方案

#1


7  

let's say you have some NSNumbers stored in an NSArray you can use this KVC collection operator:

假设您有一些存储在NSArray中的NSNumber,您可以使用此KVC集合运算符:

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

#2


1  

The reduce function is not standard in Objective-C. You can implement it as an extension of NSArray though.

reduce函数在Objective-C中不是标准函数。您可以将其实现为NSArray的扩展。

In your case, you have an array of Int in Swift. You cannot have that in Objective-C, you need an array of NSNumber.

在您的情况下,您在Swift中有一个Int数组。你不能在Objective-C中拥有它,你需要一个NSNumber数组。

Here is an implementation of reduce that should work in your case:

这是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

You can use it then with your array, something like this:

您可以将它与数组一起使用,如下所示:

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

#3


1  

For Objective-C, I would add the Higher-Order-Functions to this list of answers: https://github.com/fanpyi/Higher-Order-Functions

对于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

example:

例:

   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);

#4


0  

how to translate reduce to ObjC (or better to say how to solve your "average problem" in Objective C) was perfectly answered by André Slotta. the swift reduce is much more than that. I will try to answer the second part of your question, how the concept works in swift

AndréSlotta完美地回答了如何将简化转化为ObjC(或更好地说如何解决目标C中的“平均问题”)。快速减少远不止于此。我将尝试回答你问题的第二部分,这个概念如何在swift中起作用

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

Return the result of repeatedly calling combine with an accumulated value initialized to initial and each element of self, in turn, i.e. return combine(combine(...combine(combine(initial, self[0]), self[1]),...self[count-2]), self[count-1]).

返回结果反复调用与初始化为初始化的自身的累计值和自身的每个元素,即返回组合(组合(...组合(组合(初始,自[0]),自[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"]

#5


0  

Write an NSArray extension

写一个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;
}

fix all mistakes that I made, and that's it. Just less flexible than Swift.

解决我所犯的所有错误,就是这样。只是不如Swift灵活。

#1


7  

let's say you have some NSNumbers stored in an NSArray you can use this KVC collection operator:

假设您有一些存储在NSArray中的NSNumber,您可以使用此KVC集合运算符:

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

#2


1  

The reduce function is not standard in Objective-C. You can implement it as an extension of NSArray though.

reduce函数在Objective-C中不是标准函数。您可以将其实现为NSArray的扩展。

In your case, you have an array of Int in Swift. You cannot have that in Objective-C, you need an array of NSNumber.

在您的情况下,您在Swift中有一个Int数组。你不能在Objective-C中拥有它,你需要一个NSNumber数组。

Here is an implementation of reduce that should work in your case:

这是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

You can use it then with your array, something like this:

您可以将它与数组一起使用,如下所示:

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

#3


1  

For Objective-C, I would add the Higher-Order-Functions to this list of answers: https://github.com/fanpyi/Higher-Order-Functions

对于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

example:

例:

   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);

#4


0  

how to translate reduce to ObjC (or better to say how to solve your "average problem" in Objective C) was perfectly answered by André Slotta. the swift reduce is much more than that. I will try to answer the second part of your question, how the concept works in swift

AndréSlotta完美地回答了如何将简化转化为ObjC(或更好地说如何解决目标C中的“平均问题”)。快速减少远不止于此。我将尝试回答你问题的第二部分,这个概念如何在swift中起作用

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

Return the result of repeatedly calling combine with an accumulated value initialized to initial and each element of self, in turn, i.e. return combine(combine(...combine(combine(initial, self[0]), self[1]),...self[count-2]), self[count-1]).

返回结果反复调用与初始化为初始化的自身的累计值和自身的每个元素,即返回组合(组合(...组合(组合(初始,自[0]),自[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"]

#5


0  

Write an NSArray extension

写一个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;
}

fix all mistakes that I made, and that's it. Just less flexible than Swift.

解决我所犯的所有错误,就是这样。只是不如Swift灵活。