Swift通用数组函数查找元素的所有索引都不匹配项目 [英] Swift generic array function to find all indexes of elements not matching item

查看:174
本文介绍了Swift通用数组函数查找元素的所有索引都不匹配项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图编写一个通用数组扩展,它可以获得所有不等于值的项的索引。

示例

  let arr:[String] = [Empty,Empty,Full空,全] 
让结果:[Int] = arr.indexes(ofItemsNotEqualTo item:Empty)
//返回[2,4]


 <$ c $ 

 

我尝试了一个通用函数: c>扩展数组{

func索引< T:可比较>(ofItemsNotEqualTo item:T) - > [INT]? {
var result:[Int] = []
for self.enumerated(){
if elem!= item {
result.append(n )
}
}
返回result.isEmpty? nil:result
}
}

但是这给出了一个警告:二元运算符不能应用于元素和T类型的操作数。

所以我做了这个我投的元素(注意

 扩展数组{

func索引< T:可等分>(ofItemsNotEqualTo item:T) - > [INT]? {
var result:[Int] = [] $ b $ for(n,elem)in self.enumerated(){
if elem as? T!= item {
result.append(n)
}
}
return result.isEmpty? nil:result
}
}

但是现在看起来类型检查有出去了窗口,因为如果我传入一个整数,我得到了错误的结果

  let arr:[String] = [ 
让结果:[Int] = arr.indexes(ofItemsNotEqualTo item:100)
//返回[0,1 ,2,3,4]

帮助将不胜感激。



使用 reduce 函数有更好的方法吗?

解决方案

您已经定义了一个泛型方法

  func索引< T:Equatable>(ofItemsNotEqualTo item :T)→> [INT]? 

它的参数类型为 T which必须是
Equatable ,但与数组的 Element 类型无关。



因此

  let arr = [Empty,Empty,完整,空白,全部] 
let result = arr.indexes(ofItemsNotEqualTo:100)

编译,但 elem as? T 对所有数组给出 nil (这是!= item
元素。


你想要的是一种仅为
Equatable 元素数组定义的方法。这可以通过限制的
扩展来实现:


 扩展数组其中元素:Equatable {
func索引(ofItemsNotEqualTo item:Element) - > [INT]? {
var result:[Int] = [] $ b $ for(n,elem)in enumerated(){
if elem!= item {
result.append(n)
}
}
返回result.isEmpty? nil:result
}
}

其实我不会让返回值可选。
如果所有元素都等于给定项目,那么逻辑
返回值就是空数组。 >有没有更好的方法来使用reduce函数做到这一点?


好的,你可以 使用 reduce(),但这不是非常有效,因为在每个迭代步骤中都会创建中间数组:

 扩展数组其中元素:Equatable {
func索引(ofItemsNotEqualTo item:Element) - > [Int] {
return enumerated()。reduce([]){
$ 1.element == item? $ 0:$ 0 + [$ 1.offset]
}
}
}



你实际上有一个
filter + map操作:

 扩展数组其中Element:Equatable {
func索引(ofItemsNotEqualTo item:Element) - > [Int] {
return enumerated()。filter {$ 0.element!= item} .map {$ 0.offset}
}
}

可以使用 flatMap()简化:

 扩展数组其中,Element:Equatable {

func索引(ofItemsNotEqualTo item:Element) - > [Int] {
return enumerated()。flatMap {$ 0.element!= item? $ 0.offset:nil}
}
}

示例:

  let arr = [Empty,Empty,Full,Empty,Full] 
arr .indexes(ofItemsNotEqualTo:Full)// [0,1,3]

[1,1,1] .indexes(ofItemsNotEqualTo:1)// []

arr.indexes(ofItemsNotEqualTo:100)
//错误:无法将'Int'类型的值转换为期望的参数类型'String'


Swift 3

Trying to write a generic array extension that gets all indexes of items that DON'T equal value

example

 let arr: [String] = ["Empty", "Empty", "Full", "Empty", "Full"]
 let result: [Int] = arr.indexes(ofItemsNotEqualTo item: "Empty")
 //returns [2, 4]

I tried to make a generic function:

extension Array {

    func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?  {
        var result: [Int] = []
        for (n, elem) in self.enumerated() {
            if elem  != item {
                result.append(n)
            }
        }
        return result.isEmpty ? nil : result
    }
}

But that gives a warning: Binary operator cannot be applied to operands of type "Element" and "T".

So then I did this where I cast the element (note the as?)

extension Array {

    func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?  {
        var result: [Int] = []
        for (n, elem) in self.enumerated() {
            if elem as? T != item {
                result.append(n)
            }
        }
        return result.isEmpty ? nil : result
    }
}

But now it seems the type checking has gone out the window, because if I pass in an integer I get the wrong result

 let arr: [String] = ["Empty", "Empty", "Full", "Empty", "Full"]
 let result: [Int] = arr.indexes(ofItemsNotEqualTo item: 100)
 //returns [0, 1, 2, 3, 4]

Help would be greatly appreciated.

Is there a better way to do this with the reduce function?

解决方案

You have defined a generic method

func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?

which takes an argument of type T which is required to be Equatable, but is unrelated to the Element type of the array.

Therefore

let arr = ["Empty", "Empty", "Full", "Empty", "Full"]
let result = arr.indexes(ofItemsNotEqualTo: 100)

compiles, but elem as? T gives nil (which is != item) for all array elements.

What you want is a method which is defined only for arrays of Equatable elements. This can be achieved with a constrained extension:

extension Array where Element: Equatable {
    func indexes(ofItemsNotEqualTo item: Element) -> [Int]?  {
        var result: [Int] = []
        for (n, elem) in enumerated() {
            if elem != item {
                result.append(n)
            }
        }
        return result.isEmpty ? nil : result
    }
}

Actually I would not make the return value an optional. If all elements are equal to the given item, then the logical return value would be the empty array.

Is there a better way to do this with the reduce function?

Well, you could use reduce(), but that is not very efficient because intermediate arrays are created in each iteration step:

extension Array where Element: Equatable {
    func indexes(ofItemsNotEqualTo item: Element) -> [Int]  {
        return enumerated().reduce([]) {
            $1.element == item ? $0 : $0 + [$1.offset]
        }
    }
}

What you actually have is a "filter + map" operation:

extension Array where Element: Equatable {
    func indexes(ofItemsNotEqualTo item: Element) -> [Int]  {
        return enumerated().filter { $0.element != item }.map { $0.offset }
    }
}

which can be simplified using flatMap():

extension Array where Element: Equatable {

    func indexes(ofItemsNotEqualTo item: Element) -> [Int]  {
        return enumerated().flatMap { $0.element != item ? $0.offset : nil }
    }
}

Examples:

let arr = ["Empty", "Empty", "Full", "Empty", "Full"]
arr.indexes(ofItemsNotEqualTo: "Full") // [0, 1, 3]

[1, 1, 1].indexes(ofItemsNotEqualTo: 1) // []

arr.indexes(ofItemsNotEqualTo: 100)
// error: cannot convert value of type 'Int' to expected argument type 'String'

这篇关于Swift通用数组函数查找元素的所有索引都不匹配项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆