स्विफ्ट में आर्ग्स की चर संख्या के साथ एक फ़ंक्शन में एक सरणी पास करना


151

में स्विफ्ट प्रोग्रामिंग भाषा है, यह कहते हैं:

फ़ंक्शंस एक चर संख्या में तर्कों को भी ले सकते हैं, उन्हें एक सरणी में एकत्रित कर सकते हैं।

  func sumOf(numbers: Int...) -> Int {
      ...
  }

जब मैं संख्याओं की अल्पविराम से अलग सूची (`सारांश, 1, 2, 3, 4) के साथ इस तरह के एक समारोह को बुलाता हूं, तो उन्हें फ़ंक्शन के अंदर एक सरणी के रूप में उपलब्ध कराया जाता है।

प्रश्न: क्या होगा यदि मेरे पास पहले से ही एक संख्या है जो मैं इस फ़ंक्शन को पास करना चाहता हूं?

let numbers = [1, 2, 3, 4]
sumOf(numbers)

यह संकलक त्रुटि के साथ विफल हो जाता है, "आपूर्ति किए गए तर्कों को स्वीकार करने वाले '__conversion' के लिए एक अधिभार नहीं खोज सका"। क्या मौजूदा सरणी को उन तत्वों की सूची में बदलने का एक तरीका है जो मैं एक वैरेडिक फ़ंक्शन को पास कर सकता हूं?


1
इसके बजाय पूर्णांक सरणी लेने के लिए फ़ंक्शन को कॉन्फ़िगर क्यों नहीं करें?
मिक मैक्लम

27
यकीन है, लेकिन मैं समारोह के लेखक नहीं हो सकता है और इसे बदलने के लिए (या चाहते हैं) करने में सक्षम नहीं हो सकता है।
ओले बेगेमन

जवाबों:


97

वैभव अभी तक भाषा में नहीं है , जैसा कि देवों द्वारा पुष्टि की गई है। अभी के लिए समाधान अधिभार का उपयोग करना है या यदि आप अधिभार नहीं जोड़ सकते हैं तो प्रतीक्षा करें।


3
क्या भाषा में स्प्लिटिंग अभी तक है? मैं कॉल करने की कोशिश कर रहा हूंsumOf(...numbers)
Noitidart

इतना निराशाजनक! मैं यह भी कुछ के साथ मारा के रूप में सरल के रूप में अपने लॉग कॉल नीचे प्रतिनिधि की कोशिश कर रहा print!
मार्क ए। डोनोहो

65

यहाँ एक काम है जो मुझे मिला है। मुझे पता है कि यह बिल्कुल वैसा नहीं है जैसा आप चाहते हैं, बल्कि यह काम करने वाला लगता है।

चरण 1: वैरिएबल तर्कों के बजाय एक सरणी के साथ इच्छित फ़ंक्शन को घोषित करें:

func sumOf(numbers: [Int]) -> Int {
    var total = 0
    for i in numbers {
        total += i
    }
    return total
}

चरण 2: इसे अपने वैरेडिक फ़ंक्शन के भीतर से कॉल करें:

func sumOf(numbers: Int...) -> Int {
    return sumOf(numbers)
}

चरण 3: किसी भी तरह से कॉल करें:

var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])

यह अजीब लगता है, लेकिन यह मेरे परीक्षणों में काम कर रहा है। मुझे पता है अगर यह किसी के लिए अप्रत्याशित समस्याओं का कारण बनता है। स्विफ्ट एक ही फ़ंक्शन नाम के साथ दो कॉल के बीच के अंतर को अलग करने में सक्षम लगती है।

इस विधि के साथ, अगर Apple भाषा को @ manojid के उत्तर के रूप में अपडेट करता है, तो आपको केवल इन कार्यों को अपडेट करने की आवश्यकता होगी। अन्यथा, आपको गुजरना होगा और बहुत नाम बदलना होगा।


धन्यवाद, मुझे वर्कअराउंड पसंद है। मैं अभी भी आधिकारिक पुष्टि के लिंक को खोजने के लिए मनोजों को "सही" जवाब दूंगा कि यह सुविधा अभी तक उपलब्ध नहीं है। मुझे आशा है की तुम समझ गए होगे।
ओले बेगमैन

आप शायद गाइड और आपके फंक योग का अनुसरण कर रहे हैं (संख्या: [Int]) -> Int वास्तव में औसत की गणना कर रहा है
gfelisberto

18

आप समारोह कास्ट कर सकते हैं:

typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])

महान! यह कई (नामित) मापदंडों के साथ भी काम करता है; जैसे: func sumOf(foo numbers: Int..., bar: Bool) -> Int {};आवश्यकता हैtypealias Function = (foo: [Int], bar: Bool) -> Int;
थॉमस

महान! मेरी जिंदगी बचाओ।
जेरीझोऊ

मैं AnyObject के साथ समान चीजें कैसे कर सकता हूं ...? stackoverflow.com/questions/42016358/… धन्यवाद।
जेरीझोउ

यह बहुत बुरा विचार है। बिल्कुल शून्य गारंटी है कि यह काम करेगा।
इदमीन

1
@MattMc ज़रूर। जहां तक ​​मैं बता सकता हूं कि ऐसा कुछ भी नहीं है जो आपको केवल एक कॉल करने योग्य प्रकार को दूसरे का उपयोग करने की अनुमति देगा unsafeBitCast। यह आज भी काम कर सकता है, लेकिन जब तक कोई संदर्भ ऐसा नहीं कहता है, कंपाइलर का अगला संस्करण सचमुच यहां कुछ भी करने के लिए स्वतंत्र है (कंपाइलर त्रुटि / क्रैश / रैंडमली कोडिंग कोड ...)। असुरक्षित असुरक्षित पर गंभीर दिखने वाली चेतावनी पर एक नज़र डालें
इदमन

15

आप एक सहायक समारोह का उपयोग इस तरह कर सकते हैं:

func sumOf (numbers : [Int])  -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }

12
बशर्ते सरणियों के लिए एक संस्करण है। मुझे लगा कि प्रश्न का आधार यह है कि मूल कार्य क्या है Int...और इसे (आसानी से) बदला नहीं जा सकता है?

2
@ डेलन: सही है। मुझे ऐसा लगता है कि एक सरणी को एक वैरेडिक फ़ंक्शन में पारित करने का तरीका होना चाहिए, यह देखते हुए कि वैरेडिक तर्कों को किसी भी तरह एक ऐरे में बदल दिया जाता है।
ओले बेगेमन

1
योजनाएं, जैसे कार्य में तर्कों की चर संख्या को स्वीकार करती हैं, एक applyप्रक्रिया है। मैं कुछ लोगों को इकट्ठा करता हूं कि 'बड़बड़ा'।
गोजोनर

1
sumArrayयहाँ क्या संदर्भित है?
रोब

2

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

मेरे मामले में मैं सिर्फ एक सरणी पास करना चाहता था:

func sumOf(numbers: Array<Int>) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}

var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])

बस साझा करना चाहता था, अगर कोई और मेरी तरह सोच रहा था। ज्यादातर समय मैं इस तरह से सरणी को पास करना पसंद करूंगा, लेकिन मुझे अभी तक "स्विफ्टली" नहीं लगता। :)


1

मैंने यह किया (रैपर + आइडेंटिटी मैपिंग):

func addBarButtonItems(types: REWEBarButtonItemType...) {
    addBarButtonItems(types: types.map { $0 })
}

func addBarButtonItems(types: [REWEBarButtonItemType]) {
    // actual implementation
}

0

स्विफ्ट 5

यह @dynamicCallableसुविधा के साथ एक दृष्टिकोण है जो ओवरलोडिंग से बचने की अनुमति देता है या unsafeBitCastआपको structकॉल करने के लिए एक विशिष्ट बनाना चाहिए :

@dynamicCallable
struct SumOf {
    func dynamicallyCall(withArguments args: [Int]) -> Int {
        return args.reduce(0, +)
    }
}

let sum = SumOf()

// Use a dynamic method call.
sum(1, 2, 3) // 6

// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.