J'ai créé une classe qui contient toutes les propriétés facultatives. J'essaye de créer un var calculé qui renvoie toutes les propriétés non nulles de l'objet.

[<array of stuff>].flatMap{ $0 } semblait être le choix évident, mais quand je le bricoler dans Playground, il renvoie toujours un tableau contenant des valeurs nil.

Voici les différentes itérations de ce que j'ai essayé pour obtenir un tableau de propriétés non nulles de ma classe:

Disons que je déclare mon objet comme ceci:

let lastSearch = LastSearch(startDate: startDate, endDate: endDate, minMagnitude: 1.0, maxMagnitude: 5.0, minLongitude: nil, maxLongitude: nil, minLatitude: nil, maxLatitude: nil, minDepth: nil, maxDepth: nil)

Tentative n ° 1: Dans ma classe, j'essaye de créer une variable calculée nonNilProperties:

var nonNilProperties: Any {
    return [startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth , maxDepth].flatMap{ $0 } as Any
}

C'est ce qui s'imprime dans la console lorsque j'imprime lastSearch.nonNilProperties:

[Optional(2015-10-01 13:23:32 +0000), Optional(2015-10-07 01:43:59 +0000), Optional(1.0), Optional(5.0), nil, nil, nil, nil, nil, nil]

Tentative n ° 2:

Si je cloue sur as Any après chaque propriété, il réprime les avertissements du compilateur et les valeurs renseignées ne s'impriment pas avec "Facultatif" devant eux, mais il a toujours des valeurs null:

var nonNilProperties: Any {
    return [startDate as Any, endDate as Any, minMagnitude as Any, maxMagnitude as Any, minLongitude as Any, maxLongitude as Any, minLatitude as Any, maxLatitude as Any, minDepth as Any, maxDepth as Any].flatMap{ $0 } as [AnyObject]
}

C'est ce qui s'imprime dans la console lorsque je l'imprime:

[2015-10-01 13:23:32 +0000, 2015-10-07 01:43:59 +0000, 1, 5, <null>, <null>, <null>, <null>, <null>, <null>]

Merci pour la lecture. J'apprécie vos suggestions. Voici à quoi ressemble la classe:

class LastSearch {

  private var startDate: Date?
  private var endDate: Date?
  private var minMagnitude: Double?
  private var maxMagnitude: Double?
  private var minLongitude: Double?
  private var maxLongitude: Double?
  private var minLatitude: Double?
  private var maxLatitude: Double?
  private var minDepth: Double?
  private var maxDepth: Double?

  private var nonNilProperties: Any {
    return [startDate as Any, endDate as Any, minMagnitude as Any, maxMagnitude as Any, minLongitude as Any, maxLongitude as Any, minLatitude as Any, maxLatitude as Any, minDepth as Any, maxDepth as Any].flatMap{ $0 } as Any
  }

  init(startDate: Date?, endDate: Date?,
       minMagnitude: Double?, maxMagnitude: Double?,
       minLongitude: Double?, maxLongitude: Double?,
       minLatitude: Double?, maxLatitude: Double?,
       minDepth: Double?, maxDepth: Double?) {
    // Dates
    self.startDate = startDate
    self.endDate = endDate

    // Magnitude Values
    self.minMagnitude = minMagnitude
    self.maxMagnitude = maxMagnitude

    // Geographic Coordinates
    self.minLongitude = minLongitude
    self.maxLongitude = maxLongitude
    self.minLatitude = minLatitude
    self.maxLatitude = maxLatitude

    // Depth Values
    self.minDepth = minDepth
    self.maxDepth = maxDepth
  }      
}
1
Adrian 26 nov. 2017 à 04:36

3 réponses

Meilleure réponse

Une solution consiste à créer explicitement un nouveau tableau de type [Any] et à n'ajouter la propriété au tableau que si ce n'est pas nil.

public var nonNilProperties: [Any] {
    let allProperties: [Any?] = [startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth, maxDepth]
    var output = [Any]()
    for property in allProperties {
        if let nonNilProperty = property {
            output.append(nonNilProperty)
        }
    }
    return output
}

Ou vous pouvez utiliser flatMap qui est plus proche de votre solution d'origine (crédit à @Leo Dabus)

public var nonNilProperties: [Any] {
     return ([startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth, maxDepth] as [Any?]).flatMap { $0 }
}

Cas de test:

let lastSearch = LastSearch(startDate: Date(), endDate: Date(), minMagnitude: 1.0, maxMagnitude: 5.0, minLongitude: nil, maxLongitude: nil, minLatitude: nil, maxLatitude: nil, minDepth: nil, maxDepth: nil)
print(lastSearch.nonNilProperties)

Sortie:

[2017-11-26 02:00:13 +0000, 2017-11-26 02:00:13 +0000, 1.0, 5.0]

Cela fonctionne, mais c'est un peu gênant. En fonction de votre situation exacte, il existe probablement une meilleure façon de structurer vos données.

1
nathangitter 26 nov. 2017 à 02:10

Le premier nonNilProperties n'est pas Any, son [Any] (tableau de any). Et vous n'avez pas besoin de convertir chaque propriété en une, il le fera automatiquement. Deuxièmement, flatMap n'est pas ce dont vous avez besoin. Utilisez la carte. flatMap n'itère pas sur les éléments, mais fonctionne sur l'ensemble du tableau. Voici quelques exemples: http : //sketchytech.blogspot.ru/2015/06/swift-what-do-map-and-flatmap-really-do.html

0
Максуд Даудов 26 nov. 2017 à 01:49

Comme Leo Dabus l'a souligné dans ses commentaires, avoir les valeurs non nulles par elles-mêmes est inutile si je ne sais pas ce qu'elles sont. Cela dit, voici ce que j'ai finalement fait:

Dans la réponse Charles Prince, j'ai trouvé une méthode pour dérouler les options.

J'ai ajouté cette méthode à ma classe:

func unwrap<T>(_ any: T) -> Any {
  let mirror = Mirror(reflecting: any)
  guard mirror.displayStyle == .optional, let first = mirror.children.first else {
    return any
  }
  return unwrap(first.value)
}

Ensuite, j'ai créé une var calculée pour renvoyer un Dictionary de valeurs non nulles, en saisissant des clés et des valeurs en utilisant Mirror.

var nonNilPropertyDict: [String: Any] {

    let keys = Mirror(reflecting: self).children.flatMap { $0.label }
    let values = Mirror(reflecting: self).children.flatMap { unwrap($0.value) as! AnyObject }

    var dict = Dictionary(uniqueKeysWithValues: zip(keys, values))

    var keysToRemove = dict.keys.filter{ dict[$0] is NSNull }
    for key in keysToRemove {
      dict.removeValue(forKey: key)
    }

    return dict
}
0
Adrian 26 nov. 2017 à 18:20
47492218