2017-11-30 7 views
0

私は以下のような列挙型と構造体を持っています。構造体の配列から結果を取得する方法

enum Position: String { 
    case lw = "Left Wing" 
    case rw = "Right Wing" 
    case c = "Centre" 
    case d = "Defense" 
    case g = "Goalie" 
} 

struct PlayerInformation { 
    let firstName: String 
    let lastName: String 
    let position: Position 
    let number: Int 

} 

struct ShiftDetails { 
    let player: PlayerInformation 
    var timeOnIce: Int 
    var dateOnIce: Date 
} 

私は次のようにplayerInformationArrayを構築:

var playerInformationArray = [PlayerInformation]() 

let sidneyCrosby  = PlayerInformation.init(firstName: "Sidney", lastName: "Crosby", position: Position.c, number: 87) 
let alexOvechkin  = PlayerInformation.init(firstName: "Alex", lastName: "Ovechkin", position: Position.lw, number: 8) 
let patrickKane  = PlayerInformation.init(firstName: "Patrick", lastName: "Kane", position: Position.rw, number: 88) 

playerInformationArray.append(sidneyCrosby) 
playerInformationArray.append(alexOvechkin) 
playerInformationArray.append(patrickKane) 

私は次の配列のプレイヤー "シフト" についての情報を格納します。

var shiftDetails = [ShiftDetails]() 

私は "に関する情報を取得選択された "プレーヤーをコレクションビューから次のように表示します。

let selectedPlayer = playerInformationArray[indexPath.row] 

私は、次でshiftDetails配列を更新:除外として

shiftDetails.append(ShiftDetails.init(player: selectedPlayer, timeOnIce: timerCounter, dateOnIce: Date())) 

すべてが動作しますが、私は配列からデータを取得する方法を、苦労の理解を抱えています。例:

countをプレーヤー1人につきshiftDetailsで取得するにはどうすればよいですか?

sumをプレーヤーごとにtimeOnIceで取得するにはどうすればよいですか?

ありがとうございます!

答えて

0

これは、すべてのshiftDetailsが1つの共有配列に保持されているため、これを行う最もクリーンな方法ではないかもしれませんが、現在の設定でこれを実現するには、組み込みのfilter関数を使用して特定のプレーヤーに関する情報。これは、このような何かを見ることができる:

let selectedPlayer = playerInformationArray[indexPath.row] 
let filteredDetails = shiftDetails.filter({ $0.player == selectedPlayer }) 
let shiftCount = filteredDetails.count 
let timeOnIce = filteredDetails.reduce(0, { $0 + $1.timeOnIce }) 

別のオプションは、各プレイヤーのためのshiftDetails配列を維持するために、その時点であなたはどんなフィルタリングを行う必要はありませんでしょう。あるいは、shiftDetailsをキーがプレーヤーであり、値がshiftDetailsの配列である辞書にすることもできます。

filter関数の私の例では、Player構造体がEquatableプロトコルに準拠していると仮定しています。つまり、法的にはplayerOne == playerTwoと言うことができます。これをしないと、名前やplayerIdなどの他の固有のフィールドに一致する必要があります。

1

特定のプレーヤーが他のプレイヤーと等しいかどうかを確認する必要がある場合は、均等な演算子==を実装するEquatableプロトコルに準拠させる必要があります。スウィフトにあなたは常に読みやすくするための長い名前(キャメルケース)を好むとするとき、冗長な情報を回避しようとしてください。また

struct Player: Equatable, CustomStringConvertible { 
    let firstName: String 
    let lastName: String 
    let position: Position 
    let number: Int 
    static func ==(lhs: Player, rhs: Player) -> Bool { 
     return lhs.firstName == rhs.firstName && lhs.lastName == rhs.lastName 
    } 
    var description: String { 
     return "Player: " + firstName + " " + lastName 
    } 
} 

:また、あなたの構造体がCustomStringConvertible `に準拠して作成し、それにカスタム説明を提供することができますあなたの特性を命名して、あなたのオブジェクト名にタイプを追加しないでください。

enum Position: String { 
    case leftWing = "Left Wing" 
    case rightWing = "Right Wing" 
    case center = "Center" 
    case defense = "Defense" 
    case golie = "Goalie" 
} 

struct Shift { 
    let player: Player 
    var timeOnIce: Int 
    var dateOnIce: Date 
} 

var players: [Player] = [] 

let sidneyCrosby = Player(firstName: "Sidney", lastName: "Crosby", position: .center, number: 87) 
let alexOvechkin = Player(firstName: "Alex", lastName: "Ovechkin", position: .leftWing, number: 8) 
let patrickKane = Player(firstName: "Patrick", lastName: "Kane", position: .rightWing, number: 88) 

players += [sidneyCrosby, alexOvechkin, patrickKane] 

var shifts: [Shift] = [] 
var index = IndexPath(row: 0, section: 0) 
var selectedPlayer = players[index.row] 
let shift1 = Shift(player: selectedPlayer, timeOnIce: 3, dateOnIce: Date()) 
shifts.append(shift1) 
let shift2 = Shift(player: selectedPlayer, timeOnIce: 5, dateOnIce: Date()) 
shifts.append(shift2) 

プレイヤーとそのカウントあたりtimeOnIceプロパティを要約すると、あなたはタイプをシフトするための要素を制約するアレイを拡張することができます:

extension Array where Element == Shift { 
    func timeOnIceAndCount(for player: Player) -> (timeOnIce: Int, count: Int) { 
     return reduce((0,0)) { 
      $1.player == player ? ($0.0 + $1.timeOnIce, $0.1 + 1) : $0 
     } 
    } 
} 

let (timeOnIce, count) = shifts.timeOnIceAndCount(for: selectedPlayer) 
print(selectedPlayer) 
print("TimeOnIce:",timeOnIce) 
print("Count: ", count) 

これは、このための

Player: Sidney Crosby

TimeOnIce: 8

Count: 2

+0

感謝を印刷しますあなたはロックスターです!!しかし、私は '(for player:Player)'のタイプミスが '(for selectedPlayer:Player) 'であると信じていますが、私は次のエラーを受け取ります:' Result values in'? : '式に不一致の型があります(_、_)'と '_'が付きます –

+0

@PaulSメソッドのシグネチャの名前が正しいです。実際には、$ 1.player == selectedPlayer'の代わりに '$ 1.player == player'でなければなりません。明確化のために –

+0

感謝します。それでも「結果の値」が返されていますか? : '式に不一致があります'(_、_)と_ _ –

関連する問題