2017-01-07 1 views
0
내가 .append() 할 수있는 능력을 가지고 있으며, 유사한 정보 보유 할 수는 하늘의 배열 구조를 초기화 할 수 있기를 찾고 있어요

추가합니다 :어떻게 정보의 배열을 초기화하고

var locations = [ 
    ["title": "New York, NY", "latitude": 40.713054, "longitude": -74.007228], 
    ["title": "Los Angeles, CA", "latitude": 34.052238, "longitude": -118.243344], 
    ["title": "Chicago, IL",  "latitude": 41.883229, "longitude": -87.632398] 
] 

는이 데이터 유형 사전 배열의 배열? 나는 location에 의해 title, latitudelongitude에 액세스 할 수 찾고 있어요 나는 이런 식으로 뭔가 함께 일한 적이없는, 그래서 초기화하는 방법을 잘 오전 .append()

+2

사전의 배열입니다. 그러나 정적 필드의 배열을 저장하려고한다면 구조체의 배열이 필요합니다. – Hamish

+1

* 팁 : * Option 키를 누른 상태에서 Xcode 소스 편집기의 'locations'를 클릭하면 해당 유형이 표시됩니다. (그러나 Hamish의 제안을 따르십시오.) –

답변

1

내 구조는 사전 배열이다 [[String : Any]].

@Hamish가 주석에서 제안했듯이 데이터를 구조체 배열로 저장하는 것이 더 효과적입니다.

struct Location: CustomStringConvertible { 
    var title: String 
    var latitude: Double 
    var longitude: Double 

    var description: String { return "(title: \(title), latitude: \(latitude), longitude: \(longitude))"} 
} 

var locations = [ 
    Location(title: "New York, NY", latitude: 40.713054, longitude: -74.007228), 
    Location(title: "Los Angeles, CA", latitude: 34.052238, longitude: -118.243344), 
    Location(title: "Chicago, IL", latitude: 41.883229, longitude: -87.632398) 
] 

// Append a new location...  
locations.append(Location(title: "Boston, MA", latitude: 42.3601, longitude: -71.0589)) 

print(locations) 
[(title: New York, NY, latitude: 40.713054, longitude: -74.007228), 
(title: Los Angeles, CA, latitude: 34.052238, longitude: -118.243344), 
(title: Chicago, IL, latitude: 41.883229, longitude: -87.632398), 
(title: Boston, MA, latitude: 42.3601, longitude: -71.0589)] 
func lookUp(title: String, in locations: [Location]) -> [Location] { 
    return locations.filter { $0.title.range(of: title) != nil } 
} 

print(lookUp(title: "CA", in: locations)) 
[(title: Los Angeles, CA, latitude: 34.052238, longitude: -118.243344)] 
print(lookUp(title: "Chicago", in: locations)) 
0 : 여기

하나의 가능한 구현
0
var locations = [ 
    ["title": "New York, NY", "latitude": 40.713054, "longitude": -74.007228], 
    ["title": "Los Angeles, CA", "latitude": 34.052238, "longitude": -118.243344], 
    ["title": "Chicago, IL",  "latitude": 41.883229, "longitude": -87.632398] 
] 
for(loc) in locations { 
    if let title = loc["title"] as? String, let lat = loc["latitude"] as? Double, let lon = loc["longitude"] as? Double { 
     print("title: \(title), latitude:\(lat), longitude:\(lon)") 
    } 
} 
1

예,이 사전의 배열이다 사전 값은 String 또는 Double 유형이므로이 두 값을 모두 수용하려면 사전 유형은 <String: Any>이됩니다. 명시 적 변수 (대신 추정되는) 위치에 대한 유형을 decalairing 된 경우

은은 다음과 같습니다

var locations: [Dictionary<String, Any>] = ... 

는 당신이 Int 전달 위치를 인덱스 첨자를 사용하여 배열의 값에 액세스하려면 그 위치에서 사전의 인덱스 :

:

let firstLocation = locations[0] 
// firstLocation: [String: Any] 
// firstLocation -> [ "title": "New York, NY", "latitude": 40.713054, "longitude": -74.007228] 

당신은 사전 키에 대한 값을 액세스하는 두 번째 첨자와 깊이 파고 수 있습니다

let firstLocationTitle = locations[0]["title"] 
// firstLocationTitle: Any? 
// firstLocationTitle -> New York, NY 

let message = "I'm in" + firstLocationTitle 
// fails because operator '+' cannot be applied to operands of type 'String' and 'Any?' 

617,451,515,가 기본 문자열 유형에 대한 액세스를 얻으려면, 당신은 Any?에서 String으로 캐스팅해야합니다

let firstLocationTitle = locations[0]["title"] as! String 
// firstLocationTitle: String 
// firstLocationTitle -> New York, NY 

let message = "I'm in" + firstLocationTitle 
// message -> "I'm in New York, NY" 

새 위치를 추가하려면, 그냥 여기에, 동일한 유형을 할 필요가 당신이 추가 할 수 방법 위치에 보스턴 사전 :

let boston: [String: Any] = ["title": "Boston, MA", "latitude": 39.713054, "longitude": -88.632398] 
locations.append(boston) 
0

이 튜플로 단지 사전을 사용하는 것이 가장 수 있습니다. 그렇게하면 고유 키를 가질 수 있습니다.

var myCoordinates:(Float,Float)? 
var myCities = [String:(Float,Float)]() 

키 (문자열 형)는 도시 이름과 튜플 (두 개의 플로트 타입) 당신의 경도/latitiude 값입니다이다.

myCities["New York, NY"] = (40.713054,-74.007228) 
myCoordinates = myCities["New York, NY"]? 
print(String(describing: myCoordinates?.0)) 
print(String(describing: myCoordinates?.1)) 
myCoordinates = myCities["Los Angeles, CA"] 
print(String(describing: myCoordinates?.0)) 
print(String(describing: myCoordinates?.1)) 

이 코드는 다음과 같은 콘솔 출력을 산출한다 :

Optional(40.7130547) 
Optional(-74.007225) 
nil 
nil 
1

여기에 @vacawama의 대답 Dictionary 버전이 있습니다. 특정 유스 케이스를 더 좋게 (또는 나쁘게) 적용 할 수있는 대안입니다.

이 버전의 몇 가지 주목할만한 개선이 있습니다 사전에 열쇠를 찾고

  1. 입니다 매우 빠른 O (1), 배열에 find()을 사용하면 매우 저조한 목록으로 성장함에 따라 수행으로 어디에 수백 개의 도시들 O (N).
  2. 문자열은 힙에 할당됩니다. 즉, 설계된 좌표 struct은 성능면에서 (느린) class과 유사하게 동작합니다. 귀하의 질문은 struct에 위치 이름을 저장하는 강력한 사례를 제시하지 않았습니다.

먼저 좌표를 나타내는 구조체를 만듭니다.

print(coordinates["New York, NY"] ?? "Unknown Location”) 
> "Coordinates(latitude: 40.713054, longitude: -74.007227999999998)” 
:

struct Coordinate { 
    /// Latitude in decimal notation 
    let latitude: Double 

    /// Longitude in decimal notation 
    let longitude: Double 
} 

그런 다음

/// Empty mapping of location string to latitude-longitude 
var coordinates = [String: Coordinate]() 

가 여기에 사전을

/// Populate the locations 
coordinates["New York, NY"] = Coordinate(latitude: 40.713054, longitude: -74.007228) 
coordinates["Los Angeles, CA"] = Coordinate(latitude: 40.713054, longitude: -74.007228) 
coordinates["Chicago, IL"] = Coordinate(latitude: 40.713054, longitude: -74.007228) 

예 출력을 채우기 위해 한 가지 방법의 예 (귀하의 질문에 당) 빈 컬렉션을 만들

그게 다야! 조금 더


... 위치를 미리 알 수 있으며, 그 중 수백이없는 경우, 당신은 위해야 문자열 - 백업 enum

를 사용하여 시도 할 수있는 경우

원래의 질문에 대답하지만, Swift는 유형 시스템을 사용하여 더욱 흥미로운 접근법을 허용합니다.

Coordinate의 숫자가 Double 인 것을 보장합니다. 그러나 위치의 무결성에 대한 보장은 없습니다. 나중에 실수로 coordinates[“New york, NY”]을 입력 할 수 있습니다. "york"는 소문자이므로이 작업은 실패합니다! (또한 현재 게시 된 다른 답변도 있음).

enum Location: String { 
    case NY_NewYork = "New York, NY" 
    case CA_LosAngeles = "Los Angeles, CA" 
    case IL_Chicago = "Chicago, IL" 
} 

을 따라

/// Empty mapping of location string to latitude-longitude 
var coordinates = [Location: Coordinate]() 

/// Populate the locations 
coordinates[.NY_NewYork] = Coordinate(latitude: 40.713054, longitude: -74.007228) 
coordinates[.CA_LosAngeles] = Coordinate(latitude: 40.713054, longitude: -74.007228) 
coordinates[.IL_Chicago] = Coordinate(latitude: 40.713054, longitude: -74.007228) 

우리는 여전히 원래 "뉴욕, NY"제목이 우리의 사전 키 및 사용을 변경할 수 있지만 값 Location.NY_NewYork로 정적으로 표현된다 : 여기에 열거입니다. 이것은 컴파일러가 실수를 범할 수 있음을 의미합니다!

한 가지 더 : 이제 위치가 정적 상수 값이되었으므로 실제로 힙 할당을 두 번 내지 않고 struct 안에 다시 넣을 수 있습니다! struct 값은 열거 형 값에 대한 참조입니다.

enum Location: String { 
    case NY_NewYork = "New York, NY" 
    case CA_LosAngeles = "Los Angeles, CA" 
    case IL_Chicago = "Chicago, IL" 
} 

struct Coordinate { 
    /// The logical name of the location referenced by this coordinate 
    let location: Location 

    /// Latitude in decimal notation 
    let latitude: Double 

    /// Longitude in decimal notation 
    let longitude: Double 
} 

/// Empty mapping of location string to latitude-longitude 
var coordinates = [Location: Coordinate]() 

/// Populate the locations 
coordinates[.NY_NewYork] = Coordinate(location: .NY_NewYork, latitude: 40.713054, longitude: -74.007228) 
coordinates[.CA_LosAngeles] = Coordinate(location: .CA_LosAngeles, latitude: 40.713054, longitude: -74.007228) 
coordinates[.IL_Chicago] = Coordinate(location: .IL_Chicago, latitude: 40.713054, longitude: -74.007228) 
// or if initializing from a data source, something like... 
// if let loc = Location(rawValue: "Chicago, IL") { 
//  coordinates[loc] = Coordinate(location: loc, latitude: 40.713054, longitude: -74.007228) 
// } 

그리고 출력

print(coordinates[Location.NY_NewYork] ?? "uknown”) 
> "Coordinate(location: Location.NY_NewYork, latitude: 40.713054, longitude: -74.007227999999998)” 

쿨 :

여기에 최종 버전입니다! 이제 완벽한 유형 안전성, 거기에 위치 제목을 유지할 수있는 편의성 및 매우 고성능 아키텍처가 있습니다.

이것은 Swift를 iOS 용으로 사용하는 특별한 도구입니다.

+0

사전 조회는 빠르지 만 찾고자하는 정확한 키가 있어야합니다. 성능에 문제가있는 경우 도시 이름을 배열의 인덱스로 매핑하는 구조체 배열에서 쉽게 검색 사전을 작성할 수 있습니다. 구조체의 배열을 사용하여 "시카고 북쪽의 모든 도시를 나에게 주겠다"와 같은 질문에 답하거나 "CA"에 모든 도시를 제공 할 수도 있습니다. – vacawama

+0

@vacawama 그래, 나는 그 "정확한 열쇠"개념을 확장하기 위해 실제로 나의 대답을 수정했다. OP는 그가 열쇠를 모른다고 말하지 않았다 - 실제로 그가 아마하는 것처럼 보인다. 어쨌든, 당신이 그 사건을 만들고 싶다면, 당신이 제공 한 것보다 더 복잡한 일치자를 필요로 할 것입니다. 또한 거리 나 방향을 찾고 있다면보다 전문적인 컬렉션과 로직이 필요합니다. –

+0

런타임시 enum 값을 추가 할 수 없습니다. OP는 데이터베이스에 추가 항목을 추가 할 수 있기를 원했고 열거 형을 사용하면 그렇게 할 수 없었습니다. – vacawama

관련 문제