2017-07-11 26 views
0

我试图解决有关输入任何集合到一个通用的协议,然后寻找价值这个问题。斯威夫特3通用协议不会采取在字典中收集

我试着输入字典集合,但我得到这个错误

error: Generics Gold Challenge.playground:31:33:

error: use of unresolved identifier 'element' if collection[index] == element {

我不为什么我收到此错误或如何纠正呢?

func CheckAnyCollection<T: Collection>(in collection: T, in searchFor: T.Iterator.Element) -> [T.Index] where T.Iterator.Element: Equatable, T.Indices.Iterator.Element == T.Index 

{ 


    var results: [T.Index] = [] 

    for index in collection.indices { 

     if collection[index] == element { 

      results.append(index) 
     } 

    } 

    return results 


} 
+0

你不需要的方法只为这,这是一个班轮:'拉链(c.indices,C).lazy.filter {$ 0.1 ==元件} .MAP {$ 0.0次}' – Alexander

+0

我试图与字典类型与由 - 亚历山大提供的解决方案。 'VAR的结果= CheckAnyCollection(在:myDictionary,searchFor:3)'**,但得到这个错误**'不能转换int类型的值与预期的参数类型“_._元素”' –

+0

提供一个[最小,完整,可验证示例](https://stackoverflow.com/help/mcve) – Alexander

回答

1

我想你应该尝试这个小错误修复。

func CheckAnyCollection<T: Collection>(in collection: T, searchFor element : T.Iterator.Element) -> [T.Index] where T.Iterator.Element: Equatable, T.Indices.Iterator.Element == T.Index 

    { 


    var results: [T.Index] = [] 

    for index in collection.indices { 

    if collection[index] == element { 

     results.append(index) 
    } 

    } 

    return results 
} 
+0

我已经测试过你修改过的更正(更改为'元素')的函数,但是当我用字典集合测试它时,我得到这个错误'不能将Int类型的值转换为期望的参数类型' –

0

您的问题来自于使用Collection.Index关联类型。我不完全确定它是怎么回事,但我认为这是某种内部关联类型,并不符合你的期望。改为使用Collection.Indices.Iterator.Element。这里是你的代码,修补了

func CheckAnyCollection<C: Collection>(
    in c: C, 
    for desiredElement: C.Iterator.Element 
) -> [C.Indices.Iterator.Element] 
where C.Iterator.Element: Equatable 
{ 
    let matchingIndexElementPairs = zip(c.indices, c) 
     .lazy 
     .filter { (index, element) in element == desiredElement } 
     as LazyFilterSequence<Zip2Sequence<C.Indices, C>> 
     // annoying type annotation, but necessary to disambiguate 

    return matchingIndexElementPairs.map{ $0.0 } 
} 

print(CheckAnyCollection(in: [1, 2, 3, 2, 1], for: 2)) // => [1, 3] 

然而,也有相当这段代码的几个问题:

  1. 斯威夫特方法与lowerCamelCase命名。 UpperCamelCase是为类型保留的。
  2. 该名称具有误导性。 “CheckAny”根本不检查任何东西。
  3. 作用于实例的函数应作为扩展中该类型的实例方法实现。

这是我怎么会写这样的代码:

extension Collection where Iterator.Element: Equatable { 
    func indices(of desiredElement: Iterator.Element) -> [Indices.Iterator.Element] { 
     let matchingIndexElementPairs = zip(self.indices, self) 
      .lazy 
      .filter { (index, element) in element == desiredElement } 
      as LazyFilterSequence<Zip2Sequence<Self.Indices, Self>> 
      // annoying type annotation, but necessary to disambiguate 

     return matchingIndexElementPairs.map{ $0.0 } 
    } 
} 

这种方法可以让你有一个更自然的通话网站:

let indices2 = [1, 2, 3, 2, 1].indices(of: 2) 
print(indices2) // => [1, 3] 
+0

谢谢,我能够执行代码,但可以使用Dictionary Collection吗? @Alexander –

+0

@AlainHolly不,因为字典的元素是'(key:K,value:V)'类型的元组,它们是不可比较的。这可能不是你想要的。你是否试图获得映射到某个期望元素的键? – Alexander

+0

我意识到我错误地阅读了Swift练习,并且泛型集合是我需要使用的。 - 再次感谢 –