स्विफ्ट के एक ऐरे को चपटा करें


143

क्या स्विफ्ट flattenमें स्काला, Xtend, ग्रूवी, रूबी और सह में एक समकक्ष है ?

var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatten() // shall deliver [1,2,3,4,5,6,7,8,9] 

बेशक मैं उस के लिए कम उपयोग कर सकता है लेकिन उस थोड़े बेकार है

var flattened = aofa.reduce(Int[]()){
    a,i in var b : Int[] = a
    b.extend(i)
    return b
}

यह एक सरणी के ऑब्जेक्ट का उपयोग करने जैसा नहीं है?
फाम होन

मैंने अभी तक स्विफ्ट में नहीं देखा था, लेकिन हास्केल और एफ # में यह `कॉनकट` है - इसलिए शायद इस तरह का नाम कुछ दिखता है? - मैं सकारात्मक हूं कि यह कहीं है (सबसे एफपी लैंग्स। पता है कि मोनाड्स के बारे में है और यह सूची का बंधन है)
कार्स्टन

हाँ हैस्केल में इसे वास्तव में कंकट कहा जाता है।
क्रिश्चियन डिट्रिच

आपको andreschneider के उत्तर को स्वीकार करना चाहिए ।
रोब

जवाबों:


436

स्विफ्ट> = 3.0

reduce:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = numbers.reduce([], +)

flatMap:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = numbers.flatMap { $0 }

joined:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let joined = Array(numbers.joined())

यहां छवि विवरण दर्ज करें


3
बस इसे और अधिक सामान्य flatMapरूप से बताने के लिए, स्विफ्ट 1.2 के रूप में उपलब्ध है।
मिक मैकलम

3
joined(औपचारिक रूप से ज्ञात flatten) के बीच क्या अंतर है flatMap? क्या ऐसा है कि flatMapजुड़ते समय , यह चीजों को मैप / ट्रांसफॉर्म भी कर सकता है। लेकिन यहाँ उदाहरण में हमें वास्तव में आवश्यकता नहीं है कि हम लौटते हैं$0
Honey

6
@Dschee flatMapजाएगा या तो एक 1 डी सरणी में एक 2 डी सरणी समतल या निकालें nilमूल्यों, दोनों नहीं। यह निर्धारित करता है कि क्या करना है, अगर यह 1-स्तर के सरणी के आधार पर है, तो Elementयह एक सरणी या वैकल्पिक है - इसलिए यदि आप इसे वैकल्पिक के 2 डी सरणी से गुजरते हैं (उदाहरण के लिए [[Int?]]) तो यह इसे 1D (जैसे [Int?]) पर समतल करने का चयन करेगा । दोनों को 1-डी तक समतल करें और 2-स्तर के निल्स को हटा दें, आपको करना होगा array.flatMap { $0 }.flatMap { $0 }। दूसरे शब्दों में, आयाम-समतल करने के लिए समान है Array(array.joined())और शून्य-हटाने "समतल" के बराबर है array.filter{ $0 != nil }.map{ $0! }
स्लिप डी। थॉम्पसन

1
@ flatMapप्रश्न में वर्णित उपयोग के लिए अभी भी उपयुक्त है (1D करने के लिए एक 2D सरणी समतल)। एक क्रम से आइटम को compactMapहटाने के लिए स्पष्ट रूप nilसे, जैसा कि एक flatMapबार किया गया था।
जिम डोवी

1
@mohamadrezakoohkan सही है। चूँकि आपका सरणी प्रकार का है [[Any]], flatMapबस इसे एक प्रकार [Any]([1, 2, 3, 4, [5, 6], 7, 8, 9]) में बदल देता है। और अगर हम flatMapफिर से आवेदन करेंगे , तो हम `किसी पर भी कार्रवाई करेंगे? टाइप करें, जहां कंपाइलर को पता नहीं है कि क्या यह एक साधारण मूल्य या एक सरणी है।
andreschneider

31

स्विफ्ट मानक पुस्तकालय में वहाँ है joinedसभी प्रकार के अनुरूप के लिए लागू समारोह Sequence(या प्रोटोकॉल flattenपर SequenceType, जिसमें शामिल स्विफ्ट 3 से पहले) Array:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = Array(numbers.joined())

कुछ मामलों में उपयोग joined()करना फायदेमंद हो सकता है क्योंकि यह एक नए सरणी के बजाय एक आलसी संग्रह लौटाता है, लेकिन हमेशा एक सरणी में परिवर्तित किया जा सकता है जब इसे Array()ऊपर के उदाहरण की तरह आरंभीकृत किया जाता है।


@chrisco क्या आप इस बात की विस्तृत जानकारी दे सकते हैं कि मेरा उत्तर कैसे गलत है और "सरलतम सही उत्तर" के मानदंड क्या हैं? क्या आप यह भी बता सकते हैं कि किसी उत्तर को हटाना किसी भी तरह से प्रश्न को प्रभावित कर सकता है?
अधिकतम डेसिएटोव

पहले अपने स्निपेट को चलाने की कोशिश करें - आपको क्या लगता है कि यह क्या करता है? यह वास्तव में क्या करता है? मूल प्रश्न क्या था? क्या आपका जवाब सही है? यदि नहीं, तो इस पोस्ट की स्पष्टता को बेहतर बनाने के लिए इसे हटाना बेहतर होगा। मैंने अपने स्वयं के गलत उत्तरों के साथ भी ऐसा ही किया है।
क्रिस कॉनर

1
@chrisco आपके सुझाव के लिए बहुत बहुत धन्यवाद, लेकिन मैं उन्हें कहीं भी पोस्ट करने से पहले स्निपेट चलाता हूं। और मेरा उत्तर सही है क्योंकि यह ठीक उसी तरह के परिणाम देता है जैसे ओपी ने अनुरोध किया था और उसके लिए कम कोड का उपयोग कर रहा था। मैं स्वीकार करता हूं कि मेरा मूल उत्तर एक सरणी के बजाय आलसी संग्रह लौटा रहा था, हालांकि प्रश्न में उस पर कोई प्रतिबंध नहीं था। मुझे अब भी नहीं लगता कि एक सही उत्तर को हटाने से किसी भी तरह से प्रश्न की गुणवत्ता में सुधार होता है।
मैक्स डेसिएटोव

यह मेरी बात थी - कि आउटपुट का परीक्षण / मुद्रण करते समय, आपको ऐरे का एक सरणी मिलता है FlattenBidirectionalCollection<Array<Array<Int>>>(_base: [[1, 2, 3], [4], [5, 6, 7, 8, 9]])):। हालांकि आपकी बात मान्य है कि आप इसे एक फ्लैट ऐरे की तरह एक्सेस कर सकते हैं, इसलिए ऐसा लगेगा कि CustomStringConvertableकार्यान्वयन भ्रामक है। आपका कोड स्निपेट था और अभी भी एक परीक्षण याद कर रहा है।
क्रिस कॉनवर

1
स्विफ्ट 3.0 के रूप में, flatten()इसका नाम बदल दिया गया हैjoined()
श्री एक्सकोडर

16

स्विफ्ट 4.x / 5.x

बस सरणी में थोड़ी अधिक जटिलता जोड़ने के लिए, यदि कोई सरणी है जिसमें सरणियों का सरणी है, तो flatMapवास्तव में विफल हो जाएगा।

मान लीजिए कि सरणी है

var array:[Any] = [1,2,[[3,4],[5,6,[7]]],8]

क्या flatMapया compactMapरिटर्न है:

array.compactMap({$0})

//Output
[1, 2, [[3, 4], [5, 6, [7]]], 8]

इस समस्या को हल करने के लिए, हम लूप लॉजिक + रिकर्सन के लिए अपने सरल का उपयोग कर सकते हैं

func flattenedArray(array:[Any]) -> [Int] {
    var myArray = [Int]()
    for element in array {
        if let element = element as? Int {
            myArray.append(element)
        }
        if let element = element as? [Any] {
            let result = flattenedArray(array: element)
            for i in result {
                myArray.append(i)
            }

        }
    }
    return myArray
}

इसलिए दिए गए एरे से इस फंक्शन को कॉल करें

flattenedArray(array: array)

परिणाम है:

[1, 2, 3, 4, 5, 6, 7, 8]

यह फ़ंक्शन Intयहां के मामले को देखते हुए किसी भी प्रकार के सरणी को समतल करने में मदद करेगा

खेल का मैदान उत्पादन: यहां छवि विवरण दर्ज करें




2

स्विफ्ट 4.2

मैंने नीचे एक साधारण सरणी विस्तार लिखा है। आप उस सरणी को समतल करने के लिए उपयोग कर सकते हैं जिसमें कोई अन्य सरणी या तत्व है। शामिल होने के विपरीत () विधि।

public extension Array {
    public func flatten() -> [Element] {
        return Array.flatten(0, self)
    }

    public static func flatten<Element>(_ index: Int, _ toFlat: [Element]) -> [Element] {
        guard index < toFlat.count else { return [] }

        var flatten: [Element] = []

        if let itemArr = toFlat[index] as? [Element] {
            flatten = flatten + itemArr.flatten()
        } else {
            flatten.append(toFlat[index])
        }

        return flatten + Array.flatten(index + 1, toFlat)
    }
}

उपयोग:

let numbers: [Any] = [1, [2, "3"], 4, ["5", 6, 7], "8", [9, 10]]

numbers.flatten()

1

का एक और अधिक सामान्य कार्यान्वयन reduce,

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = reduce(numbers,[],+)

यह एक ही बात को पूरा करता है, लेकिन जो चल रहा है उसमें अधिक जानकारी दे सकता है reduce

Apple के डॉक्स से,

func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U

विवरण

बदले में प्रारंभिक और अनुक्रम के प्रत्येक तत्व से जुड़े एक संचित मूल्य के साथ बार-बार बुलाए गए संयोजन के परिणाम को वापस करें ।


आपके कोड के साथ मुझे:Use of unresolved identifier 'reduce'
जेसन मूर

1

संशोधित @ RahmiBozdag का उत्तर, 1. सार्वजनिक एक्सटेंशन में विधियाँ सार्वजनिक हैं। 2. हटाए गए अतिरिक्त विधि, जैसा कि प्रारंभ सूचकांक हमेशा शून्य होगा। 3. मुझे एनआईएल और ऑप्शनल के लिए कॉम्पेक्टमप को अंदर रखने का कोई तरीका नहीं मिला क्योंकि टी के अंदर विधि हमेशा [कोई भी है], किसी भी सुझाव का स्वागत किया जाता है।

 let array = [[[1, 2, 3], 4], 5, [6, [9], 10], 11, nil] as [Any?]

 public extension Array {

 func flatten<T>(_ index: Int = 0) -> [T] {
        guard index < self.count else { 
            return [] 
        }

        var flatten: [T] = []

        if let itemArr = self[index] as? [T] {
            flatten += itemArr.flatten()
        } else if let element = self[index] as? T {
            flatten.append(element)
        }
        return flatten + self.flatten(index + 1)
   }

}

let result: [Any] = array.flatten().compactMap { $0 }
print(result)
//[1, 2, 3, 4, 5, 6, 9, 10, 11]

0

आप निम्न विधि का उपयोग करके नेस्टेड सरणी को समतल कर सकते हैं:

var arrays = [1, 2, 3, 4, 5, [12, 22, 32], [[1, 2, 3], 1, 3, 4, [[[777, 888, 8999]]]]] as [Any]

func flatten(_ array: [Any]) -> [Any] {

    return array.reduce([Any]()) { result, current in
        switch current {
        case(let arrayOfAny as [Any]):
            return result + flatten(arrayOfAny)
        default:
            return result + [current]
        }
    }
}

let result = flatten(arrays)

print(result)

/// [1, 2, 3, 4, 5, 12, 22, 32, 1, 2, 3, 1, 3, 4, 777, 888, 8999]

0

Apple स्विफ्ट संस्करण 5.1.2 (स्विफ्टलैंग -1100.0.278 क्लैंग -1100.0.33.9)
लक्ष्य: x86_64-apple-darwin19.2.0

स्क्रीनशॉट

let optionalNumbers = [[1, 2, 3, nil], nil, [4], [5, 6, 7, 8, 9]]
print(optionalNumbers.compactMap { $0 }) // [[Optional(1), Optional(2), Optional(3), nil], [Optional(4)], [Optional(5), Optional(6), Optional(7), Optional(8), Optional(9)]]
print(optionalNumbers.compactMap { $0 }.reduce([], +).map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(optionalNumbers.compactMap { $0 }.flatMap { $0 }.map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(optionalNumbers.compactMap { $0 }.joined()).map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

let nonOptionalNumbers = [[1, 2, 3], [4], [5, 6, 7, 8, 9]]
print(nonOptionalNumbers.compactMap { $0 }) // [[1, 2, 3], [4], [5, 6, 7, 8, 9]]
print(nonOptionalNumbers.reduce([], +)) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nonOptionalNumbers.flatMap { $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(nonOptionalNumbers.joined())) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

0

स्विफ्ट 5.1

public extension Array where Element: Collection {

    func flatten() -> [Element.Element] {
        return reduce([], +)
    }
}

मामले में आप इसे शब्दकोश मूल्यों के लिए भी चाहते हैं:

public extension Dictionary.Values where Value : Collection {
    func flatten() -> [Value.Element]{
         return self.reduce([], +)
    }
}


-1

मैट्रिक्स [[myDTO]] है?

स्विफ्ट 5 में आप इसका उपयोग कर सकते हैं


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.