2016-01-21 6 views
5

क्या स्विफ्ट के मूल Dictionary से [NSDictionary initWithObjects: forKeys:] के बराबर है?स्विफ्ट के बराबर `[NSDictionary initWithObjects: forKeys:]`

मैं कुंजी और मूल्यों के साथ दो सरणियों है और उन्हें एक शब्दकोश में डालने के लिए चाहते हैं। ऑब्जेक्टिव-सी में मैं इसे इस तरह करना चाहते हैं:

NSArray *keys = @[@"one", @"two", @"three"]; 
NSArray *values = @[@1, @2, @3]; 
NSDictionary *dict = [[NSDictionary alloc] initWithObjects: values forKeys: keys]; 
पाठ्यक्रम मैं दोनों सरणियों के माध्यम से एक काउंटर के साथ पुनरावृति कर सकते हैं के

, एक var dict: [String:Int] का उपयोग करें और कदम से कदम सामान जोड़ें। लेकिन यह एक अच्छा समाधान प्रतीत नहीं होता है। zip और enumerate का उपयोग करना संभवतः एक ही समय में पुन: प्रयास करने के बेहतर तरीके हैं। हालांकि इस दृष्टिकोण का मतलब एक परिवर्तनीय शब्दकोश है, न कि एक अपरिवर्तनीय।

let keys = ["one", "two", "three"] 
let values = [1, 2, 3] 
// ??? 
let dict: [String:Int] = ["one":1, "two":2, "three":3] // expected result 

उत्तर

3

वन-लाइनर, zip और reduce का उपयोग कर:

let dict = zip(keys, values).reduce([String:Int]()){ var d = $0; d[$1.0] = $1.1; return d } 

आप + ऑपरेटर को परिभाषित करते हुए reduce अभिव्यक्ति छोटा कर सकते हैं Dictionary और tuple के लिए:

func +<K,V>(lhs: [K:V], rhs: (K, V)) -> [K:V] { 
    var result = lhs 
    result[rhs.0] = rhs.1 
    return result 
} 

let dict = zip(keys, values).reduce([String:Int](), combine: +) 
+0

ऑपरेटर के रूप में उपयोग करने के लिए '+' को परिभाषित करना बहुत सार्थक नहीं है। कोई अन्य फ़ंक्शन नाम अधिक आत्म व्याख्यात्मक होगा। – orkoden

+1

एक तरफ '+' का अर्थ अर्थपूर्ण अर्थ है, क्योंकि यह शब्दकोश में एक नया तत्व जोड़ता है, दूसरी ओर यह जोड़ने के बजाय प्रतिस्थापित भी कर सकता है ताकि इसका प्रभाव हमेशा संचयी न हो। मैं व्यक्तिगत रूप से इसे सार्थक समझता हूं; यह केवल मुझे हो सकता है, हालांकि :) – Cristik

4

आप बस काम करते हुए structs के साथ शुद्ध स्विफ्ट समाधान initWithObjects:forKeys:

let keys = ["one", "two", "three"] 
let values = [1, 2, 3] 
var dict = NSDictionary.init(objects: values, forKeys: keys) 
+2

ध्यान दें कि इस दृष्टिकोण के साथ अपने 'dict' प्रकार के हो जाएगा' NSDictionary' और नहीं '[स्ट्रिंग: इंट]'। आप इस तरह 'स्ट्रिंग: इंट]' को डाउनकास्ट करते हैं: 'NSDictionary.init (ऑब्जेक्ट्स: वैल्यू, केकेज़: चाबियाँ) के रूप में![स्ट्रिंग: Int] ' – JAL

+1

मुझे पता है कि मैं इसका उपयोग करता हूं, लेकिन यह केवल 'एनएससीपीआईइंग' और 'AnyObject' ऑब्जेक्ट्स के अनुरूप कुंजी के लिए काम करता है। स्विफ्ट शब्दकोश उपरोक्त उदाहरण या 'enums', 'structs' आदि में' Int' जैसे आदिम प्रकारों के लिए भी काम करते हैं। मैं' NSDictionary' का उपयोग नहीं करना चाहता लेकिन स्विफ्ट के मूल 'शब्दकोश' – orkoden

+0

इस मामले में 'Int' हैं 'NSNumber' में स्वचालित रूप से परिवर्तित हो गया है, क्योंकि आप 'प्रिंट (dict.allValues.first? .dynamicType)' – orkoden

3

की स्विफ्ट बराबर उपयोग कर सकते हैं। एक ट्यूपल के रूप में अपने दो सरणी के माध्यम से फिर से चलाने के लिए zip का उपयोग करें, और फिर प्रत्येक कुंजी के लिए एक शब्दकोश बनाएं, tuple में मान।

struct SomeStruct { 
    var someVal: Int? 
} 

var keys = [String]() 
var values = [SomeStruct]() 

for index in 0...5 { 
    keys.append(String(index)) 
    values.append(SomeStruct(someVal: index)) 
} 

var dict = [String : Any]() 

for (key, value) in zip(keys, values) { 
    dict[key] = value 
} 

print(dict) // "["4": SomeStruct(someVal: Optional(4)), "2": SomeStruct(someVal: Optional(2)), "1": SomeStruct(someVal: Optional(1)), "5": SomeStruct(someVal: Optional(5)), "0": SomeStruct(someVal: Optional(0)), "3": SomeStruct(someVal: Optional(3))]" 

तुम भी forEachzip पर इस्तेमाल कर सकते हैं:

var dict = [String : Any]() 
zip(keys, values).forEach { dict[$0.0] = $0.1 } 
print(dict) // "["4": SomeStruct(someVal: Optional(4)), "2": SomeStruct(someVal: Optional(2)), "1": SomeStruct(someVal: Optional(1)), "5": SomeStruct(someVal: Optional(5)), "0": SomeStruct(someVal: Optional(0)), "3": SomeStruct(someVal: Optional(3))]\n" 
+0

यह मेरा समाधान भी था, मुझे इसे अपने प्रश्न में जोड़ना चाहिए था। नकारात्मकता यह है कि आप इस मामले में एक परिवर्तनीय शब्दकोश के साथ खत्म हो जाते हैं। – orkoden

+1

@orkoden आह मैं देखता हूँ। मैंने एक समाधान जोड़ा जो 'मानचित्र' का उपयोग करता है जो थोड़ा कम वर्बोज़ है। उम्मीद है कि आपकी जरूरतों के लिए काम करता है। मैं आपके लिए एक अपरिवर्तनीय शब्दकोश बनाने के बारे में सोचता रहूंगा। – JAL

+2

आपको ज़िप (कुंजी, मान) में '(कुंजी, मान) के लिए' ऐरे (Zip2Sequence (कुंजी, मान)) की आवश्यकता नहीं है, 'पर्याप्त है। – orkoden

1
let keys = ["one", "two", "three"] 
let values = [1, 2, 3] 

func createDict<K:Hashable,V>(keys: [K], values:[V])->[K:V] { 

    var dict: [K:V] = [:] 

    // add validity checks here by yourself ! 
    // and return early, or throw an error ... 

    keys.enumerate().forEach { (index,element) ->() in 
     dict[element] = values[index] 
    } 
    return dict 
} 

let dict = createDict(keys, values: values) 
// ["one": 1, "three": 3, "two": 2] 

let dict2:[Int:Any] = createDict([1,2,3,4,5], values: [true,"two",3.4,5,[1,2,3]]) 
// [5: [1, 2, 3], 2: "two", 3: 3.4, 1: true, 4: 5] 

क्या अंतर अगर यह जिप समाधान की तुलना में है है? मुश्किल कहने के लिए ... मेरे लिए ज़िप प्रकार एनोटेशन सबसे बड़ी समस्या

let a:Zip2Sequence<[Int],[Any]> = zip([1,2,3,4,5], [true,"two",3.4,5,[1,2,3]]) 
var d:[Int:Any] = [:] 
a.forEach { (key, value) ->() in 
    d[key] = value 
} 
print(d) 
// [5: [1, 2, 3], 2: "two", 3: 3.4, 1: true, 4: 5] 

है, लेकिन गणना समाधान भी है एक छोटा सा तेज

1

के रूप में स्विफ्ट 4 आप से एक शब्दकोश सीधे बना सकते हैं कुंजी/मान जोड़े के अनुक्रम:

let keys = ["one", "two", "three"] 
let values = [1, 2, 3] 

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

print(dict) // ["one": 1, "three": 3, "two": 2] 

मतलब यह है कि सभी चाबियाँ अलग हैं, अन्यथा यह एक क्रम अपवाद के साथ रद्द कर देगा।

चाबियाँ अलग होने की गारंटी नहीं कर रहे हैं, तो आप

let keys = ["one", "two", "one"] 
let values = [1, 2, 3] 

let dict = Dictionary(zip(keys, values), uniquingKeysWith: { $1 }) 

print(dict) // ["one": 3, "two": 2] 

दूसरा तर्क एक बंद जो निर्धारित करता है जो मान "जीत" डुप्लिकेट चाबी के मामले में है कर सकते हैं।

संबंधित मुद्दे