স্ট্রিং টাইপ সহ একটি এনুম গণনা করবেন কীভাবে?


530
enum Suit: String {
    case spades = "♠"
    case hearts = "♥"
    case diamonds = "♦"
    case clubs = "♣"
}

উদাহরণস্বরূপ, আমি কীভাবে এমন কিছু করতে পারি:

for suit in Suit {
    // do something with suit
    print(suit.rawValue)
}

ফলাফল উদাহরণ:

♠
♥
♦
♣

কোন পরিস্থিতিতে আপনি টাইপটি জানেন না?
mtbennett

আপনি ঠিক বলেছেন, এক্ষেত্রে এটি স্ট্রিং টাইপ।
লুকিয়েন


22
এগুলি কি বিদ্রূপ নয় যে এগুলিকে গণনা বলা হয়, তবে তারা সুইফটে গণনা করতে এত বেদনাদায়ক বিরক্তিকর হয়?
চার্লটন প্রোভাতাস 21

3
@ চার্লটনপ্রাভাটাস যদি সুইফটে একমাত্র ত্রুটি হত তবে আমি এটিকে একটি দিন বলতাম। এর জন্য কতজন লোক বিভিন্ন কাজের প্রস্তাব দিচ্ছে তা দেখে , আমি কেবল আমার কীবোর্ডটি জেনেছি।
কিওয়ার্টি_সো 5'18

উত্তর:


266

সুইফট 4.2+

সুইফট ৪.২ (এক্সকোড 10 সহ) দিয়ে শুরু করুন, এতে CaseIterableউপকৃত হওয়ার জন্য কেবল প্রোটোকল কনফারেন্স যুক্ত করুন allCases। এই প্রোটোকল কনফারেন্স যুক্ত করতে, আপনাকে কেবল কোথাও লিখতে হবে:

extension Suit: CaseIterable {}

এনাম যদি আপনার নিজস্ব হয় তবে আপনি সরাসরি ঘোষণায় কনফরমেন্সটি নির্দিষ্ট করতে পারেন:

enum Suit: String, CaseIterable { case spades = "♠"; case hearts = "♥"; case diamonds = "♦"; case clubs = "♣" }

তারপরে নিম্নলিখিত কোডটি সমস্ত সম্ভাব্য মান মুদ্রণ করবে:

Suit.allCases.forEach {
    print($0.rawValue)
}

পূর্ববর্তী সুইফ্ট সংস্করণগুলির সাথে সামঞ্জস্যতা (3.x এবং 4.x)

আপনার যদি সুইফট 3.x বা 4.0 সমর্থন করার প্রয়োজন হয় তবে আপনি নিম্নলিখিত কোডটি যুক্ত করে সুইফট 4.2 বাস্তবায়ন নকল করতে পারেন:

#if !swift(>=4.2)
public protocol CaseIterable {
    associatedtype AllCases: Collection where AllCases.Element == Self
    static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
    static var allCases: [Self] {
        return [Self](AnySequence { () -> AnyIterator<Self> in
            var raw = 0
            var first: Self?
            return AnyIterator {
                let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
                if raw == 0 {
                    first = current
                } else if current == first {
                    return nil
                }
                raw += 1
                return current
            }
        })
    }
}
#endif

@ দিমিত্রিপেটখভ আমি সাহায্য করে খুশি হব, কিন্তু: (1) আপনি কি কোডটির সর্বশেষতম সংস্করণ পেয়েছেন তা নিশ্চিত? (কিছু ক্র্যাশ এক মাস আগে ঠিক করা হয়েছিল) এবং (২) দয়া করে আপনার কাস্টম ধরণের এমন একটি এমসিভিই দিন যা ক্র্যাশটি পুনরুত্পাদন করতে পারে এবং আপনার এক্সকোডের সংস্করণ।
সিউর

এটি আমার জন্য ডিবাগ বিল্ডগুলির জন্য সূক্ষ্ম কাজ করে, তবে আমি যখনই একটি রিলিজ তৈরি করব এবং টেস্টফ্লাইটে আপলোড করার সাথে সাথে এটি ক্র্যাশ হয়ে যায়। অ্যাপল কি একরকম এড়িয়ে চলেছে?
ড্যানিয়েল উড

1
দেখে মনে হচ্ছে আপনার সংস্করণ কেসআইটরেটরের অন্তর্নির্মিত সংস্করণটির তুলনায় একটি ইতিবাচক রয়েছে। আমি আপনার সংস্করণ সহ অন্য ফাইলে সংজ্ঞায়িত এনামগুলি প্রসারিত করতে পারি। আপনি যদি এক্সটেনশনে সমস্ত ক্ষেত্রে সর্বজনীন করেন তবে আপনি বিভিন্ন ফ্রেমওয়ার্কগুলিতে সংজ্ঞায়িত এনামগুলিও প্রসারিত করতে পারেন।
adamfowlerphoto

1
@ সাইবারমিউ আমি এটি পরিষ্কার করার জন্য উত্তর আপডেট করেছি। সুইফট বই এবং এক্সকোড 10 রিলিজ নোটগুলি কেসআইটেবলের উল্লেখ করেছে আমার উত্তরের উত্তরোত্তর এবং তারা সরল উদাহরণ ব্যবহার করেছে যেখানে এনামের সাহায্য নেই String, বর্তমান স্ট্যাক ওভারফ্লো প্রশ্নের বিপরীতে question
সিউর

1
আমি "# if! Swift (> = 4.2)" এর গুরুত্বকে গুরুত্ব দিতে চাই। আপনি যদি আপনার কোডটি 4.2-র সুইফ্ট করার আগে লিখেছিলেন এবং আপনি যদি আপনার পরীক্ষার ডিভাইসে স্থানীয়ভাবে নির্মাণের জন্য এক্সকোড সংস্করণ 11.4 ব্যবহার করেন, তখন কোডটি "# if! Swift (> = 4.2)" মুছে ফেলতে ভুলে গিয়েছিলেন, সমস্ত কিছু ঠিক হয়ে যাবে। কিন্তু যখন আপনার অ্যাপটি অ্যাপ্লিকেশন স্টোর বা পরীক্ষার ফ্লাইট থেকে ডাউনলোড করা হবে, তখন কোডটির এই অংশটি আপনার অ্যাপ্লিকেশানটি ক্রাশ করবে। এই ধরণের বাগ স্পট করা বা ডিবাগ করা খুব শক্ত।
অলিভার ঝাং

524

এই পোস্টটি এখানে প্রাসঙ্গিক https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift

মূলত প্রস্তাবিত সমাধান হ'ল

enum ProductCategory : String {
     case Washers = "washers", Dryers = "dryers", Toasters = "toasters"

     static let allValues = [Washers, Dryers, Toasters]
}

for category in ProductCategory.allValues{
     //Do something
}

188
চমৎকার, তবে ... আপনাকে অবশ্যই নিজের এলিমেন্টের উপাদানগুলি দুবার প্রবেশ করতে হবে - একবার গণনার জন্য, একবার অলভ্যালুগুলির জন্য। একজন যেমন চান তেমন মার্জিত নয়।
জে ইমারম্যান

2
"তবে" এর সাথে সম্মত হন ... তবে নিবন্ধে যেমন বলা হয়েছে সম্ভবত একটি সমস্যা আছে যে এনাম সত্যই একটি সেট এবং অতএব অর্ডারহীন ... আপনি মনে রাখবেন ... অর্ডার ক্ষেত্রে সংজ্ঞায়িত করা খারাপ শুরু হবে না!
রাউজএক্সসিটার

3
জাভাতে সংকলকটি এটি আপনার জন্য করে, সম্ভবত সুইফট 2.0 এটিও করবে will বিশেষত জাভাতে সমস্ত এনাম একটি বিবরণ পায় (জাভাতে টো স্ট্রিং) পদ্ধতি যা স্ট্রিংকে কেস নাম হিসাবে দেয় (ওয়াশার্স, ...) এবং কেসগুলির একটি সেট স্বয়ংক্রিয়ভাবে তৈরি হয়ে যায়। জাভা আপনাকে পজিশনাল ইনডেক্সিংও দেয়। আমি যেমন বলেছি, সম্ভবত সুইফট ২.০
হাওয়ার্ড লোভাত

1
আদর্শভাবে আপনার সি # বাস্তবায়নের মতো কিছু থাকবে যা আপনি করতে পারেন Enum.Values(typeof(FooEnum))তবে এক্সটেনশন পদ্ধতি হিসাবে প্রকাশ করা (মানচিত্র বা হ্রাস করার মতো)। FooEnum.values() :: values(EnumType -> [EnumType])
রডরিগেল্প

1
নিবন্ধটি প্রতিটি এনাম মান তৈরির সম্পর্কে শেষে একটি ভাল পয়েন্ট তৈরি করে একটি ইউনিট পরীক্ষার সাথে অ্যালভ্যালু অ্যারেতে। যাইহোক, আমি এখনও আরও কাউকে আরও উপাদান যুক্ত করতে দেখতে পাচ্ছি, তবে ইউনিট পরীক্ষায় তাদের প্রয়োগ না করা যা এখনও শুরুর দিকে আমাদের পিছনে ফেলেছে, নিশ্চিতভাবে জেনে নেই যে সমস্ত এনাম মানগুলি অ্যালভ্যালুতে রাখা হয়েছে।
ডোনলিয়া

278

আমি iterateEnum()স্বেচ্ছাচারী enumধরণের ক্ষেত্রে পুনরাবৃত্তি হওয়া ক্ষেত্রে একটি ইউটিলিটি ফাংশন করেছি ।

এখানে উদাহরণ ব্যবহার:

enum Suit: String {
    case Spades = "♠"
    case Hearts = "♥"
    case Diamonds = "♦"
    case Clubs = "♣"
}

for f in iterateEnum(Suit) {
    println(f.rawValue)
}

কোন ফলাফল:

♠
♥
♦
♣

তবে, এটি কেবল ডিবাগ বা পরীক্ষার উদ্দেশ্যে: এটি বেশ কয়েকটি অননুমোদিত Swift1.1 সংকলক আচরণের উপর নির্ভর করে, সুতরাং এটি নিজের ঝুঁকিতে ব্যবহার করুন।

কোডটি এখানে:

func iterateEnum<T: Hashable>(_: T.Type) -> GeneratorOf<T> {
    var cast: (Int -> T)!
    switch sizeof(T) {
        case 0: return GeneratorOf(GeneratorOfOne(unsafeBitCast((), T.self)))
        case 1: cast = { unsafeBitCast(UInt8(truncatingBitPattern: $0), T.self) }
        case 2: cast = { unsafeBitCast(UInt16(truncatingBitPattern: $0), T.self) }
        case 4: cast = { unsafeBitCast(UInt32(truncatingBitPattern: $0), T.self) }
        case 8: cast = { unsafeBitCast(UInt64($0), T.self) }
        default: fatalError("cannot be here")
    }

    var i = 0
    return GeneratorOf {
        let next = cast(i)
        return next.hashValue == i++ ? next : nil
    }
}

অন্তর্নিহিত ধারণাটি হ'ল:

  • সম্পর্কিত ধরণের সাথে enumবাদ দিয়ে মেমরির উপস্থাপনা enumহ'ল কেসগুলির একটি সূচক কেবল যখন মামলার গণনা হয় 2...256, এটি UInt8কখন 257...65536, কখন এটির সাথে সমানUInt16 হয়। সুতরাং, এটি unsafeBitcastস্বাক্ষরযুক্ত স্বাক্ষর পূর্ণসংখ্যার প্রকার থেকে হতে পারে ।
  • .hashValue এনাম মানগুলির ক্ষেত্রে সূচকের সমান।
  • .hashValueঅবৈধ সূচক থেকে বিটকাস্ট করা এনাম মানগুলি 0

সুইফট 2 এর জন্য সংশোধিত এবং @ কামেট্রিক্সমের উত্তর থেকে কাস্টিং আইডিয়া প্রয়োগ করা হয়েছে :

func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
    var i = 0
    return anyGenerator {
        let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
        return next.hashValue == i++ ? next : nil
    }
}

সুইফট 3 এর জন্য সংশোধিত:

func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
    var i = 0
    return AnyIterator {
        let next = withUnsafePointer(to: &i) {
            $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
        }
        if next.hashValue != i { return nil }
        i += 1
        return next
    }
}

Swift3.0.1 এর জন্য সংশোধিত:

func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
    var i = 0
    return AnyIterator {
        let next = withUnsafeBytes(of: &i) { $0.load(as: T.self) }
        if next.hashValue != i { return nil }
        i += 1
        return next
    }
}

20
দুর্দান্ত এবং একমাত্র উত্তর যা প্রশ্নের উত্তর দেয়! তবে হ্যাঁ ... এটি স্পর্শ করবে না! প্রয়াসের জন্য +1, যদিও!
ডটটোস্ট্রিং

আমি কেবল আমার উত্তর পোস্ট করেছি যা মূলত একইভাবে কাজ করে (কেবলমাত্র এই উত্তরটি পরে দেখেছি)। এতে সুইফট ২.০ বিটা 6 এবং ভাষার আধুনিক বৈশিষ্ট্য ব্যবহার করা হয়েছে।
কামেট্রিক্সম

2
সুইফট 3 সংস্করণটি ভালভাবে কাজ করে। কেবলমাত্র কিছুটা ব্যবহারের সংশোধন করা দরকার: এফরেট্রেইনাম (স্যুট.সেলফ) এর জন্য {মুদ্রণ (f.rawValue)}
জিন দে লিসা

16
+1 এটি বেশ উজ্জ্বল। এটি আইএমএইচওও ব্যবহার করার জন্য খুব চালাক, এটি প্রমাণ করে যে এটি প্রতিটি বড় সুইফট সংস্করণ পরিবর্তনে উল্লেখযোগ্যভাবে ভেঙে যায়। লেখকের কৃতিত্বের জন্য, সুইফট 3 সংস্করণটি বিটা থেকে বেরিয়ে আসার এক মাস আগে করা হয়েছিল ... আপনি যদি এই উত্তরটি নিয়ে চলেছেন এবং এই সমস্ত withUnsafePointer withMemoryReboundএবং pointeeস্টাফ শিখছেন , তবে এটিকে সমস্ত উপায়ে ব্যবহার করুন। অন্যথায়, আমি এড়াতে চাই।
ড্যান রোজনস্টার্ক

5
আমি কেবল এটি যুক্ত করতে চাই এখন সুইফ্ট 4 এ ভাঙ্গা হয়েছে তবে কেবল লিনাক্সের উপর, সুতরাং উপরের মন্তব্যগুলিতে +1 করুন যে এটি ব্যবহার করা খুব চালাক।
অ্যান্ড্রু প্লামার

130

অন্যান্য সমাধান কাজ করে তবে তারা সকলেই সম্ভাব্য র্যাঙ্ক এবং স্যুটগুলির সংখ্যা বা প্রথম এবং শেষ র‌্যাঙ্কটি কী হতে পারে তার অনুমান করে make সত্য, কার্ডের ডেকের বিন্যাস সম্ভবত সম্ভাব্য ভবিষ্যতে খুব বেশি পরিবর্তন ঘটবে না। তবে সাধারণভাবে এটি কোড লিখার চেয়ে কম, যা যতটা সম্ভব অনুমান করা যায়। আমার সমাধান:

আমি Suitএনামে একটি কাঁচা প্রকার যুক্ত করেছি , তাই আমি কেসগুলি Suit(rawValue:)অ্যাক্সেস করতে ব্যবহার করতে পারি Suit:

enum Suit: Int {
    case Spades = 1
    case Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
            case .Spades:
                return "spades"
            case .Hearts:
                return "hearts"
            case .Diamonds:
                return "diamonds"
            case .Clubs:
                return "clubs"
        }
    }
    func color() -> String {
        switch self {
        case .Spades:
            return "black"
        case .Clubs:
            return "black"
        case .Diamonds:
            return "red"
        case .Hearts:
            return "red"
        }
    }
}

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
            case .Ace:
                return "ace"
            case .Jack:
                return "jack"
            case .Queen:
                return "queen"
            case .King:
                return "king"
            default:
                return String(self.rawValue)
        }
    }
}

কার্ড এর বাস্তবায়ন নীচে createDeck() পদ্ধতি । init(rawValue:)একটি অনুপলব্ধ আরম্ভকারী এবং একটি returnsচ্ছিক প্রদান করে। বিবৃতি দেওয়ার সময় উভয়টিতে আনপ্রেপিং করে এবং এর মূল্য পরীক্ষা করে, সংখ্যা Rankবা Suitকেসের সংখ্যা অনুমান করার দরকার নেই :

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
    func createDeck() -> [Card] {
        var n = 1
        var deck = [Card]()
        while let rank = Rank(rawValue: n) {
            var m = 1
            while let suit = Suit(rawValue: m) {
                deck.append(Card(rank: rank, suit: suit))
                m += 1
            }
            n += 1
        }
        return deck
    }
}

createDeckপদ্ধতিটি কীভাবে কল করবেন তা এখানে :

let card = Card(rank: Rank.Ace, suit: Suit.Clubs)
let deck = card.createDeck()

12
নিখুঁত সেরা উত্তর আমি এই বিষয়টির বিভিন্ন থ্রেডে দেখেছি। খুব মার্জিত. এটি ইন্টার টাইপ এনুমারেশনগুলির সাথে কাজ করে তবে আমি আশ্চর্য হয়েছি যে কেউ কীভাবে অন্য ধরণের (স্ট্রিং, কাস্টম প্রকার ইত্যাদি) মাধ্যমে পুনরাবৃত্তি করতে পারে।
জে ইমারম্যান

3
এটি অবশ্যই সেরা সমাধান। একটি বিষয় লক্ষণীয়। বইটিতে উদাহরণ হিসাবে এটিতে "কেস স্পেডস = 1" নেই যেমন এসড্ডুর্সমা আছে। আমি এই প্রথম ধরিনি। এটি একটি বিকল্প, বা আপনি কেবল "var m = 0" ব্যবহার করতে পারেন
জোশুয়া গুসসেন

10
এটি এই ধারণাটি তৈরি করে যে কাঁচা মানগুলি অনুক্রমিক। যখন এটি সত্য হয় না, উদাহরণস্বরূপ যখন এনাম বিট মাস্ক ফ্ল্যাগগুলি উপস্থাপন করে, লুপ অকাল আগেই প্রস্থান করে।
জিম

1
এই সমাধানটি ধরে নিয়েছে যে আপনি এর সংজ্ঞাটি সংশোধন করতে পারেন Suit। আপনি এই উদাহরণটিতে করতে পারেন, তবে অনুশীলনটি আপনাকে বোঝানো হয়েছিল যাতে enumsআপনাকে কোনও বাহ্যিক উত্স থেকে এসেছিল তাই আপনাকে কাজ করাতে হবে ।
জোশ জে

1
কেবলমাত্র আমি যে অভিযোগ করতে চাই তা হ'ল আমি এটিকে স্থির পদ্ধতি হিসাবে বলতে পারি না, তবে প্রথমে একটি কার্ড অবজেক্ট তৈরি করতে হবে।
কিয়েড

76

আমি বিটস এবং বাইটগুলির চারপাশে হোঁচট খেয়েছি এবং একটি এক্সটেনশন তৈরি করেছি যা পরে আমি জানতে পেরেছিলাম @ মুদ্রারোর জবাবের সাথে খুব মিল রয়েছে । এটি এভাবে ব্যবহার করা হয়:

enum E : EnumCollection {
    case A, B, C
}

Array(E.cases())    // [A, B, C]

লক্ষণীয় যে এটি কোনও মান সম্পর্কিত সম্পর্কিত মান ব্যতীত ব্যবহারযোগ্য। মনে রাখবেন যে এটি কোনও এনামের জন্য কাজ করে না ums

সঙ্গে @rintaro এর উত্তর, এই কোড একটি enum অন্তর্নিহিত উপস্থাপনা ব্যবহার করে। এই উপস্থাপনাটি নথিভুক্ত নয় এবং ভবিষ্যতে পরিবর্তিত হতে পারে যা এটি ভেঙে দেবে। আমি উত্পাদনে এটি ব্যবহারের প্রস্তাব দিই না।

কোড (সুইফট 2.2, এক্সকোড 7.3.1, এক্সকোড 10 এ কাজ করছে না):

protocol EnumCollection : Hashable {}
extension EnumCollection {
    static func cases() -> AnySequence<Self> {
        typealias S = Self
        return AnySequence { () -> AnyGenerator<S> in
            var raw = 0
            return AnyGenerator {
                let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }
    }
}

কোড (সুইফট 3, এক্সকোড 8.1, এক্সকোড 10 এ কাজ করছে না):

protocol EnumCollection : Hashable {}
extension EnumCollection {
    static func cases() -> AnySequence<Self> {
        typealias S = Self
        return AnySequence { () -> AnyIterator<S> in
            var raw = 0
            return AnyIterator {
                let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }
    }
}

আমার কেন দরকার তা সম্পর্কে আমার কোনও ধারণা নেই typealiasতবে সংকলক এটি ছাড়া অভিযোগ করে।


10
এই উত্তরটি আমার উত্তরের চেয়ে আরও ভাল, বিশেষত কাস্টিং অংশে :)
rintaro

তবে আমি মনে করি এটি কেবল সামান্য এন্ডিয়ান পরিবেশে কাজ করে?
rintaro

5
এক্সকোড 8 বিটা 6 এটি আবার পরিবর্তন হয়েছে! আমি নিম্নলিখিত ত্রুটিটি পেয়েছি init 'আরআর' অনুপলব্ধ: মেমরিআরবাউন্ড (সাথে: ক্ষমতা: _) 'ব্যবহার করে অস্থায়ীভাবে মেমরিটিকে অন্য লেআউট-সামঞ্জস্যপূর্ণ টাইপ হিসাবে দেখতে পারেন `
বিভ্রান্ত ভোরলন

1
@ কনফিউজডভোরলন: উপরে উত্তর দেখুন রিন্টারো দ্বারা: প্রতিস্থাপন withUnsafePointer... pointee}দ্বারাwithUnsafePointer(to: &i) { $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } }
স্টিফান

1
এটি এখন Xcode 10 হিসাবে কাজ করবে না বলে মনে হচ্ছে (আমি জানি সুইফট 4.2 এর সাথে এটির প্রয়োজন হবে না) তবে
এক্সকোড

26

ForwardIndexTypeপ্রোটোকল প্রয়োগ করে আপনি এনামের মাধ্যমে পুনরাবৃত্তি করতে পারেন ।

ForwardIndexTypeপ্রোটোকল একটি সংজ্ঞায়িত করতে হবে successor()উপাদানের মাধ্যমে ধাপে ফাংশন।

enum Rank: Int, ForwardIndexType {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King

    // ... other functions

    // Option 1 - Figure it out by hand
    func successor() -> Rank {
        switch self {
            case .Ace:
              return .Two
            case .Two:
              return .Three

            // ... etc.

            default:
              return .King
        }
    }

    // Option 2 - Define an operator!
    func successor() -> Rank {
        return self + 1
    }
}

// NOTE: The operator is defined OUTSIDE the class
func + (left: Rank, right: Int) -> Rank {
    // I'm using to/from raw here, but again, you can use a case statement
    // or whatever else you can think of

    return left == .King ? .King : Rank(rawValue: left.rawValue + right)!
}

একটি উন্মুক্ত বা বদ্ধ পরিসরে ( ..<বা ...) অভ্যন্তরীণভাবে successor()ফাংশনটি কল করবে যা আপনাকে এটি লেখার অনুমতি দেয়:

// Under the covers, successor(Rank.King) and successor(Rank.Ace) are called to establish limits
for r in Rank.Ace...Rank.King {
    // Do something useful
}

2
আমি এটি প্রশ্নের সর্বাধিক "যথাযথ" উত্তর বলে মনে করি, এমনকি সর্বাধিক "মার্জিত" (অতিরিক্ত কোডের সাথে এখানে অন্যান্য বিকল্পগুলি সহ্য করার ক্ষেত্রে প্রয়োজনীয় কোডগুলিও) সীমার মধ্যে ব্যবহারের সময় ফলাফলটি বাক্য গঠন প্রদান করে (সিনট্যাক্সটিই আমি enumsratable sans workarounds যেখানে enums করতে সক্ষম হবে আশা করি)। ধন্যবাদ! যদিও এটি লক্ষণীয় যে অপারেটর ওভারলোডিং যদি উত্তরাধিকারী () কে (যা লোভনীয় মনে হয়) ছাড়াও অন্য কোথাও নিযুক্ত করা হয় তবে অবশ্যই বাধ্যতামূলক আনরেপিং বিপজ্জনক। এছাড়াও, ইনফিক্স অপ্রয়োজনীয় বলে মনে হচ্ছে ...?
আইওএস গেমার

সর্বশেষতম সুইফট ভাষার স্পেসিফিকেশন
প্রতিবিম্বিত

একটি সঠিকভাবে সংজ্ঞায়িত successor()পদ্ধতি (প্রথম বিকল্প) এর সাথে enumসম্পর্কিত ধরণের প্রয়োজন মুছে ফেলবে । +1
nhgrif

1
তবে এই মার্জিত উত্তরটি স্ট্রিং এনামগুলির পক্ষে কাজ করবে না?
আলী

সর্বাধিক "যথাযথ" / সেরা অনুশীলনের সমাধান! + 1-এডি
সিউ চিং পং-আসুকা কেনজি-

18

এই সমস্যা এখন অনেক সহজ। এখানে আমার সুইফট ৪.২ সমাধান:

enum Suit: Int, CaseIterable {
  case None
  case Spade, Heart, Diamond, Club

  static let allNonNullCases = Suit.allCases[Spade.rawValue...]
}

enum Rank: Int, CaseIterable {
  case Joker
  case Two, Three, Four, Five, Six, Seven, Eight
  case Nine, Ten, Jack, Queen, King, Ace

  static let allNonNullCases = Rank.allCases[Two.rawValue...]
}

func makeDeck(withJoker: Bool = false) -> [Card] {
  var deck = [Card]()
  for suit in Suit.allNonNullCases {
    for rank in Rank.allNonNullCases {
      deck.append(Card(suit: suit, rank: rank))
    }
  }
  if withJoker {
    deck.append(Card(suit: .None, rank: .Joker))
  }
  return deck
}

প্রাক 4.2:

আমি এই সমাধানটি পছন্দ করি যা আমি সুইফটে " তালিকা বোঝার সন্ধানের পরে একসাথে রেখেছিলাম

এটি স্ট্রিংয়ের পরিবর্তে ইন্ট রাউ ব্যবহার করে তবে এটি দু'বার টাইপ করা এড়ানো যায়, এটি রেঞ্জগুলি অনুকূলিতকরণ করতে দেয় এবং হার্ড কোড কাঁচা মান দেয় না।

এটি আমার আসল সমাধানের একটি সুইফট 4 সংস্করণ তবে উপরের 4.2 এর উন্নতি দেখুন:

enum Suit: Int {
  case None
  case Spade, Heart, Diamond, Club

  static let allRawValues = Suit.Spade.rawValue...Suit.Club.rawValue
  static let allCases = Array(allRawValues.map{ Suit(rawValue: $0)! })
}
enum Rank: Int {
  case Joker
  case Two, Three, Four, Five, Six
  case Seven, Eight, Nine, Ten
  case Jack, Queen, King, Ace

  static let allRawValues = Rank.Two.rawValue...Rank.Ace.rawValue
  static let allCases = Array(allRawValues.map{ Rank(rawValue: $0)! })
}
func makeDeck(withJoker: Bool = false) -> [Card] {
  var deck = [Card]()
  for suit in Suit.allCases {
    for rank in Rank.allCases {
      deck.append(Card(suit: suit, rank: rank))
    }
  }
  if withJoker {
    deck.append(Card(suit: .None, rank: .Joker))
  }
  return deck
}

ওহ, আমি এখন দেখছি যে খনিটি মূলত স্যুটান রুটজানালার্ডের সমান।
অ্যাডাজাকম

1
আসলে, আমি আপনার বাস্তবায়ন ভাল পছন্দ। আমি মনে করি এটি আরও পরিষ্কার! 1 upvote। আসলে সর্বাধিক ভোট দেওয়া উত্তরগুলি খুব চতুর এবং ভবিষ্যতে অবশ্যই ভেঙে যায়। আপনার ভবিষ্যতে কিছু স্থিতিশীলতার প্রতিশ্রুতি দিয়েছেন।
jvarela

17

নীতিগতভাবে এটি এটি এইভাবে ধরে নেওয়া সম্ভব যে আপনি এনামের ক্ষেত্রে কাঁচা মান অ্যাসাইনমেন্ট ব্যবহার করবেন না:

enum RankEnum: Int {
  case Ace
  case One
  case Two
}

class RankEnumGenerator: Generator {
    var i = 0
    typealias Element = RankEnum
    func next() -> Element? {
        let r = RankEnum.fromRaw(i)
        i += 1
        return r
    }
}

extension RankEnum {
    static func enumerate() -> SequenceOf<RankEnum> {
        return SequenceOf<RankEnum>({ RankEnumGenerator() })
    }
}

for r in RankEnum.enumerate() {
    println("\(r.toRaw())")
}

7
এটি দুর্দান্ত তবে এটি কেবল 0
রবার্ট

@ রবার্ট, যেমন উপরে আমার মন্তব্যে বলা হয়েছে: "আপনি
এনমের

হ্যাঁ - কাঁচা মানগুলি ব্যবহার করবেন না, পাশাপাশি অন্তর্নিহিত প্রকারটি অন্তর্ভুক্ত করার জন্য সেট করুন। দ্রুতগতিতে স্যুট উদাহরণের মতো এনামের জন্য আপনার কোনও প্রকারের দরকার নেই। enum ItWontWorkForThisEnum {case a, b, c}
রবার্ট

একটি টিপল যদি গণনার মামলার সাথে সম্পর্কিত হয় তবে কীভাবে এই সমস্যাটি সমাধান করা হবে?
রুজএক্সসিটার

আপনি খুব সহজেই একটি এনুমের সাথে একটি টুপলকে সংযুক্ত করতে পারবেন না।
nhgrif

13

আপনি যদি এনামকে একটি কাঁচা ইন্টার মান দেন তবে এটি লুপিংকে আরও সহজ করে তুলবে।

উদাহরণস্বরূপ, আপনি anyGeneratorএমন কোনও জেনারেটর পেতে ব্যবহার করতে পারেন যা আপনার মানগুলি জুড়ে গণনা করতে পারে:

enum Suit: Int, CustomStringConvertible {
    case Spades, Hearts, Diamonds, Clubs
    var description: String {
        switch self {
        case .Spades:   return "Spades"
        case .Hearts:   return "Hearts"
        case .Diamonds: return "Diamonds"
        case .Clubs:    return "Clubs"
        }
    }
    static func enumerate() -> AnyGenerator<Suit> {
        var nextIndex = Spades.rawValue
        return anyGenerator { Suit(rawValue: nextIndex++) }
    }
}
// You can now use it like this:
for suit in Suit.enumerate() {
    suit.description
}
// or like this:
let allSuits: [Suit] = Array(Suit.enumerate())

তবে এটি দেখতে মোটামুটি সাধারণ প্যাটার্নের মতো মনে হচ্ছে, আমরা কেবল কোনও প্রোটোকল অনুসারে কোনও এনাম টাইপকে গণনার যোগ্য করে তুলতে পারলে কি ভাল লাগবে না? সুইফট ২.০ এবং প্রোটোকল এক্সটেনশানগুলির সাথে ভাল, এখন আমরা পারি!

কেবল আপনার প্রকল্পে এটি যুক্ত করুন:

protocol EnumerableEnum {
    init?(rawValue: Int)
    static func firstValue() -> Int
}
extension EnumerableEnum {
    static func enumerate() -> AnyGenerator<Self> {
        var nextIndex = firstRawValue()
        return anyGenerator { Self(rawValue: nextIndex++) }
    }
    static func firstRawValue() -> Int { return 0 }
}

এখন যে কোনও সময় আপনি এনাম তৈরি করবেন (যতক্ষণ না এটির কোনও কাঁচা মূল্য রয়েছে) আপনি প্রোটোকলের সাথে খাঁটি করে এটি গুণনীয় করতে পারেন:

enum Rank: Int, EnumerableEnum {
    case Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}
// ...
for rank in Rank.enumerate() { ... }

যদি আপনার এনাম মানগুলি 0(ডিফল্ট) দিয়ে শুরু না হয় তবে firstRawValueপদ্ধতিটি ওভাররাইড করুন :

enum DeckColor: Int, EnumerableEnum {
    case Red = 10, Blue, Black
    static func firstRawValue() -> Int { return Red.rawValue }
}
// ...
let colors = Array(DeckColor.enumerate())

প্রতিস্থাপন সহ চূড়ান্ত মামলা বর্গ, simpleDescriptionসঙ্গে আরো মান CustomStringConvertible প্রোটোকল , ভালো হবে:

enum Suit: Int, CustomStringConvertible, EnumerableEnum {
    case Spades, Hearts, Diamonds, Clubs
    var description: String {
        switch self {
        case .Spades:   return "Spades"
        case .Hearts:   return "Hearts"
        case .Diamonds: return "Diamonds"
        case .Clubs:    return "Clubs"
        }
    }
}
// ...
for suit in Suit.enumerate() {
    print(suit.description)
}

সুইফট 3 সিনট্যাক্স:

protocol EnumerableEnum {
    init?(rawValue: Int)
    static func firstRawValue() -> Int
}

extension EnumerableEnum {
    static func enumerate() -> AnyIterator<Self> {
        var nextIndex = firstRawValue()

        let iterator: AnyIterator<Self> = AnyIterator {
            defer { nextIndex = nextIndex + 1 }
            return Self(rawValue: nextIndex)
        }

        return iterator
    }

    static func firstRawValue() -> Int {
        return 0
    }
}

NextIndex ++ দ্রুত 3 এ মুছে ফেলা হবে - প্রতিস্থাপন হিসাবে আপনি কী প্রস্তাব করেন - var NextIndex = প্রথম রোলভ্যালু () যে কোনও জেনারেটরকে ফেরত দিন {স্ব (কাঁচা মূল্য: নেক্সটআইডেক্স ++)}
আভি

এটা বের করে আনা। ডিফার {নেক্সটআইডেক্স + = 1 Any যেকোন জেনারেটরকে ফিরিয়ে দিন {স্ব (কাঁচা মূল্য: নেক্সটআইডেক্স) A
এভি

12

সুইফট ২.২ + এ আপডেট হয়েছে

func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
    var i = 0
    return AnyGenerator {
        let next = withUnsafePointer(&i) {
            UnsafePointer<T>($0).memory
        }
        if next.hashValue == i {
            i += 1
            return next
        } else {
            return nil
        }
    }
}

এটি সুইফট ২.২ ফর্মটিতে কোড আপডেট হয়েছে কমিট্রিক্সমের উত্তর @

জন্য সুইফট 3.0+ (অনেক ধন্যবাদ @Philip )

func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
    var i = 0
    return AnyIterator {
        let next = withUnsafePointer(&i) {
            UnsafePointer<T>($0).pointee
        }
        if next.hashValue == i {
            i += 1
            return next
        } else {
            return nil
        }
    }
}

@ সিলভানস্কি আপনি কি বোঝাতে চেয়েছিলেন দয়া করে?
ale_stro

ওফস, দুঃখিত, আমি পুনরায় যাচাই করেছিলাম এবং একটি খেলার মাঠ বাগ ছিল: বাস্তব প্রকল্পে এই কোডটি প্রত্যাশা মতো কাজ করে, ধন্যবাদ! =)
সিলভানস্কি

1
দুর্দান্ত সমাধান! এছাড়াও, সুইফট 3 এ ন্যূনতম পরিবর্তনগুলির সাথে সূক্ষ্মভাবে কাজ করে ('যেকোনও জেনারেটর' নামকরণ করে 'যেকোনইট্রেটার' এবং '.মেমরি'র নামকরণ' .পয়েন্টি 'করা হয়েছে)।
ফিলিপ

9

সুইফট 5 সমাধান:

enum Suit: String, CaseIterable {
    case spades = "♠"
    case hearts = "♥"
    case diamonds = "♦"
    case clubs = "♣"
}

// access cases like this:

for suitKey in Suit.allCases {
    print(suitKey)
}

7

আমি .allValuesআমার কোড জুড়ে নিজেকে অনেক কিছু করতে দেখলাম । আমি শেষ পর্যন্ত কেবল একটি Iteratableপ্রোটোকলের সাথে খাপ খাইয়ে নেওয়ার এবং একটি rawValues()পদ্ধতি রাখার উপায় খুঁজে পেয়েছি ।

protocol Iteratable {}
extension RawRepresentable where Self: RawRepresentable {

    static func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
        var i = 0
        return AnyIterator {
            let next = withUnsafePointer(to: &i) {
                $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
            }
            if next.hashValue != i { return nil }
            i += 1
            return next
        }
    }
}

extension Iteratable where Self: RawRepresentable, Self: Hashable {
    static func hashValues() -> AnyIterator<Self> {
        return iterateEnum(self)
    }

    static func rawValues() -> [Self.RawValue] {
        return hashValues().map({$0.rawValue})
    }
}


// Example
enum Grocery: String, Iteratable {
    case Kroger = "kroger"
    case HEB = "h.e.b."
    case Randalls = "randalls"
}

let groceryHashes = Grocery.hashValues() // AnyIterator<Grocery>
let groceryRawValues = Grocery.rawValues() // ["kroger", "h.e.b.", "randalls"]

7

সুইফট 4.2 সহ এক্সকোড 10

enum Filter: String, CaseIterable {

    case salary = "Salary"
    case experience = "Experience"
    case technology = "Technology"
    case unutilized = "Unutilized"
    case unutilizedHV = "Unutilized High Value"

    static let allValues = Filter.allCases.map { $0.rawValue }
}

ডাকা

print(Filter.allValues)

ছাপে:

["বেতন", "অভিজ্ঞতা", "প্রযুক্তি", "অব্যবহৃত", "অব্যবহৃত উচ্চ মূল্য"]


পুরানো সংস্করণ

জন্য enumপ্রতিনিধিত্বমূলকInt

enum Filter: Int {
    case salary
    case experience
    case technology
    case unutilized
    case unutilizedHV

    static let allRawValues = salary.rawValue...unutilizedHV.rawValue  // First to last case
    static let allValues = allRawValues.map { Filter(rawValue: $0)!.rawValue }
}

এটিকে কল করুন:

print(Filter.allValues)

ছাপে:

[0, 1, 2, 3, 4]


জন্য enumপ্রতিনিধিত্বমূলকString

enum Filter: Int {
    case salary
    case experience
    case technology
    case unutilized
    case unutilizedHV

    static let allRawValues = salary.rawValue...unutilizedHV.rawValue  // First to last case
    static let allValues = allRawValues.map { Filter(rawValue: $0)!.description }
}

extension Filter: CustomStringConvertible {
    var description: String {
        switch self {
        case .salary: return "Salary"
        case .experience: return "Experience"
        case .technology: return "Technology"
        case .unutilized: return "Unutilized"
        case .unutilizedHV: return "Unutilized High Value"
        }
    }
}

ডাকা

print(Filter.allValues)

ছাপে:

["বেতন", "অভিজ্ঞতা", "প্রযুক্তি", "অব্যবহৃত", "অব্যবহৃত উচ্চ মূল্য"]


7

সম্পাদনা: সুইফ্ট বিবর্তন প্রস্তাব এসই -0154 এনাম কেসগুলির উত্পন্ন সংগ্রহ এই সমস্যার একটি স্তরের নেতৃত্বাধীন সমাধানের প্রস্তাব দেয় । আমরা এটি সুইফট ৪.২ এবং আরও নতুনতে দেখতে পাচ্ছি। প্রস্তাবটি কিছু কাজের ক্ষেত্রের দিকেও নির্দেশ করে যা ইতিমধ্যে এখানে উল্লিখিত সাথে মিল রয়েছে তবে তবুও এটি আকর্ষণীয় হতে পারে।

আমি সম্পূর্ণরূপে আমার মূল পোস্টটি রাখব।


এটি সুইফট 3-এর সাথে অভিযোজিত @ পিম্মানখের উত্তরের উপর ভিত্তি করে আরও একটি পন্থা ।

public protocol EnumCollection: Hashable {}

extension EnumCollection {

public static func allValues() -> [Self] {
    typealias S = Self

    let retVal = AnySequence { () -> AnyIterator<S> in
        var raw = 0
        return AnyIterator {
            let current = withUnsafePointer(to: &raw) {
                 $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee }
            }
            guard current.hashValue == raw else { return nil }
            raw += 1
            return current
        }
    }

    return [S](retVal)
}

5
enum Rank: Int {
    ...
    static let ranks = (Rank.Ace.rawValue ... Rank.King.rawValue).map{Rank(rawValue: $0)! }

}
enum Suit {
    ...
    static let suits = [Spades, Hearts, Diamonds, Clubs]
}

struct Card {
    ...
    static func fullDesk() -> [Card] {
        var desk: [Card] = []
        for suit in Suit.suits {
            for rank in Rank.ranks {
                desk.append(Card(rank: rank,suit: suit))
            }
        }
        return desk
    }
}

এ কেমন?


ধন্যবাদ, এটি আমার প্রয়োজন মতো কাজ করে। তবে মানচিত্রটি বন্ধ করার কোনও সুযোগ কি সূচক দিয়ে নয় নাম অনুসারে পাওয়ার জন্য?
মিখাইল

4

আপনি এটির মতো গণনা করার চেষ্টা করতে পারেন

enum Planet: String {
    case Mercury
    case Venus
    case Earth
    case Mars

    static var enumerate: [Planet] {
        var a: [Planet] = []
        switch Planet.Mercury {
            case .Mercury: a.append(.Mercury); fallthrough
            case .Venus: a.append(.Venus); fallthrough
            case .Earth: a.append(.Earth); fallthrough
            case .Mars: a.append(.Mars)
        }
    return a
    }
}

Planet.enumerate // [Mercury, Venus, Earth, Mars]

1
এটি অনেকটা অকেজো কোড! এটি সমতুল্য static var enumerate = [Mercury, Venus, Earth, Mars], এটি সর্বাধিক ভোটিত জবাবের তুলনায় একটি সাবপার উত্তর তৈরি করে stackoverflow.com/a/24137319/1033581
সিউর

@ Cœur এই উত্তরটি আপনার কোনও কেস মিস করবেন না এর গ্যারান্টি দিতে সংকলকটি ব্যবহারের গুরুত্বপূর্ণ সুবিধা রয়েছে।
dchakarov

@ সিউর যা আপনাকে ব্যবহারকারীর ত্রুটি করতে দেয় একই সমস্যা, যেমন আপনি লেখার return [Mercury, Venus, Mars]পরিবর্তে সংকলক অভিযোগ করবেন নাreturn [Mercury, Venus, Earth, Mars]
chaচাকারভ

: @dchakarov আমি স্বচ্ছতার জন্য, একটি উত্তর হিসাবে উন্নতি পোস্ট করার সিদ্ধান্ত নিয়েছে stackoverflow.com/a/50409525/1033581
Coeur

@ কেউর যদি আপনার নতুন উত্তরে আপনি রিটার্নের স্টেটমেন্টটি প্রতিস্থাপন করে এই return [.spades, .hearts, .clubs]সংকলকটি কিছু বলবে না এবং তারপরে আপনি কোডটিতে এটি ব্যবহার করার চেষ্টা করবেন তখন আপনি পাবেন [TestApp.Suit.spades, TestApp.Suit.hearts, TestApp.Suit.clubs]- এটি আমার বক্তব্য ছিল - আপনি যদি কোনও বড় বিষয় নিয়ে কাজ করছেন এনাম এবং আপনাকে সময়ে সময়ে কেস যুক্ত করতে হবে বা সরিয়ে ফেলতে হবে, আপনার সমাধানটি বাদ দেওয়ার ত্রুটির প্রবণতা রয়েছে যখন বর্তমান উত্তরটি সংক্ষিপ্ত না হলেও নিরাপদ।
dchakarov

4

সুইফ্ট 3-এ, যখন অন্তর্নিহিত এনাম থাকে rawValue, আপনি Strideableপ্রোটোকলটি প্রয়োগ করতে পারেন । সুবিধাগুলি হ'ল মানগুলির কোনও অ্যারে অন্য কিছু পরামর্শের মতো তৈরি করা হয় নি এবং স্ট্যান্ডার্ড সুইফ্ট "ইন" লুপের জন্য কাজ করে, যা একটি সুন্দর বাক্য গঠন করে।

// "Int" to get rawValue, and Strideable so we can iterate
enum MyColorEnum: Int, Strideable {
    case Red
    case Green
    case Blue
    case Black

    // required by Strideable
    typealias Stride = Int

    func advanced(by n:Stride) -> MyColorEnum {
        var next = self.rawValue + n
        if next > MyColorEnum.Black.rawValue {
            next = MyColorEnum.Black.rawValue
        }
        return MyColorEnum(rawValue: next)!
    }

    func distance(to other: MyColorEnum) -> Int {
        return other.rawValue - self.rawValue
    }

    // just for printing
    func simpleDescription() -> String {
        switch self {
        case .Red: return "Red"
        case .Green: return "Green"
        case .Blue: return "Blue"
        case .Black: return "Black"
        }
    }
}

// this is how you use it:
for i in MyColorEnum.Red ... MyColorEnum.Black {
    print("ENUM: \(i)")
}

আহ, ঠিক আমি ফরওয়ার্ডইন্ডেক্সটাইপটি প্রতিস্থাপনের জন্য যা খুঁজছিলাম। এখন আমার পুনরাবৃত্তিগুলি ব্যবহারের সাইটে ভাল দেখাচ্ছে ... ঠিক সঠিক সুইফটি উপায়।
অ্যান্ড্রু ডানকান

4

এই সমাধানটি পঠনযোগ্যতা এবং রক্ষণাবেক্ষণের সঠিক ভারসাম্যকে আঘাত করে।

struct Card {

    // ...

    static func deck() -> Card[] {
        var deck = Card[]()
        for rank in Rank.Ace.toRaw()...Rank.King.toRaw() {
            for suit in [Suit.Spades, .Hearts, .Clubs, .Diamonds] {
                let card = Card(rank: Rank.fromRaw(rank)!, suit: suit)
                deck.append(card)
            }
        }
    return deck
    }
}

let deck = Card.deck()

আমার মতে এটিই সেরা সমাধান। আমি যখন স্যুইফ্ট কোডটি দেখি, বেশিরভাগ ক্ষেত্রে পঠনযোগ্যতা অবজেক্টের চেয়ে ভাল হয় না। তবে এটি হতে পারে, যদি প্রোগ্রামাররা তাদের কোডের পাঠকদের আরও বেশি মনোযোগ দেয় । তাদের ভবিষ্যতের উদাহরণস্বরূপ :)
ভিলিম কুর্জ

4

দুঃখিত, আমার উত্তরটি সুনির্দিষ্ট ছিল যে আমি কী করতে চাইলে এই পোস্টটি কীভাবে ব্যবহার করেছি। যারা এই প্রশ্ন উপর পদস্খলন, একটি উপায় খুঁজছেন জন্য এটি একটি enum মধ্যে একটি মামলা, এটা এই ভাবে (নতুন সুইফট 2) করতে হয়:

সম্পাদনা: লোয়ারকেস ক্যামেল কেস এখন সুইফট 3 এনাম মানের জন্য মান

// From apple docs: If the raw-value type is specified as String and you don’t assign values to the cases explicitly, each unassigned case is implicitly assigned a string with the same text as the name of that case.

enum Theme: String
    {
    case white, blue, green, lavender, grey
    }

func loadTheme(theme: String)
    {
    // this checks the string against the raw value of each enum case (note that the check could result in a nil value, since it's an optional, which is why we introduce the if/let block
    if let testTheme = Theme(rawValue: theme)
        {
        // testTheme is guaranteed to have an enum value at this point
        self.someOtherFunction(testTheme)
        }
    }

একটি এনামে গণনা সম্পর্কে যারা ভাবছেন তাদের জন্য, এই পৃষ্ঠায় প্রদত্ত উত্তরগুলি যাতে একটি স্ট্যাটিক ভার থাকে / সমস্ত এনাম মানের একটি অ্যারে যুক্ত থাকে তা সঠিক। টিভিওএসের সর্বশেষ অ্যাপল উদাহরণ কোডটিতে হুবহু একই কৌশল রয়েছে।

বলা হচ্ছে, তাদের ভাষাগুলিতে আরও সুবিধাজনক ব্যবস্থা তৈরি করা উচিত (অ্যাপল, আপনি কি শুনছেন?)!


3

পরীক্ষাটি ছিল: এক্সপেরিমেন্ট

কার্ডে এমন একটি পদ্ধতি যুক্ত করুন যা র‌্যাঙ্ক এবং স্যুটের প্রতিটি সংমিশ্রণের একটি কার্ড সহ কার্ডের একটি পূর্ণ ডেক তৈরি করে।

সুতরাং পদ্ধতি যুক্ত করা (এবং এখনও শেখানো হয়নি এমন স্টাফ ব্যবহার না করে) প্রদত্ত কোডটি সংশোধন বা উন্নত না করে আমি এই সমাধানটি নিয়ে এসেছি:

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }

    func createDeck() -> [Card] {
        var deck: [Card] = []
        for rank in Rank.Ace.rawValue...Rank.King.rawValue {
            for suit in Suit.Spades.rawValue...Suit.Clubs.rawValue {
                let card = Card(rank: Rank(rawValue: rank)!, suit: Suit(rawValue: suit)!)
                //println(card.simpleDescription())
                deck += [card]
            }
        }
        return deck
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
let deck = threeOfSpades.createDeck()

3

এখানে একটি পদ্ধতি যা আমি উভয়কে পুনরাবৃত্তি করতে ব্যবহার করি enumএবং এক থেকে একাধিক মান প্রকার সরবরাহ করিenum

enum IterateEnum: Int {
    case Zero
    case One
    case Two
    case Three
    case Four
    case Five
    case Six
    case Seven

    //tuple allows multiple values to be derived from the enum case, and
    //since it is using a switch with no default, if a new case is added,
    //a compiler error will be returned if it doesn't have a value tuple set
    var value: (french: String, spanish: String, japanese: String) {
        switch self {
        case .Zero: return (french: "zéro", spanish: "cero", japanese: "nuru")
        case .One: return (french: "un", spanish: "uno", japanese: "ichi")
        case .Two: return (french: "deux", spanish: "dos", japanese: "ni")
        case .Three: return (french: "trois", spanish: "tres", japanese: "san")
        case .Four: return (french: "quatre", spanish: "cuatro", japanese: "shi")
        case .Five: return (french: "cinq", spanish: "cinco", japanese: "go")
        case .Six: return (french: "six", spanish: "seis", japanese: "roku")
        case .Seven: return (french: "sept", spanish: "siete", japanese: "shichi")
        }
    }

    //Used to iterate enum or otherwise access enum case by index order.
    //Iterate by looping until it returns nil
    static func item(index: Int) -> IterateEnum? {
        return IterateEnum.init(rawValue: index)
    }

    static func numberFromSpanish(number: String) -> IterateEnum? {
        return findItem { $0.value.spanish == number }
    }

    //use block to test value property to retrieve the enum case        
    static func findItem(predicate: ((_: IterateEnum) -> Bool)) -> IterateEnum? {

        var enumIndex: Int = -1
        var enumCase: IterateEnum?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = IterateEnum.item(index: enumIndex)

            if let eCase = enumCase {

                if predicate(eCase) {
                    return eCase
                }
            }
        } while enumCase != nil
        return nil
    }
}

var enumIndex: Int = -1
var enumCase: IterateEnum?

// Iterate until item returns nil
repeat {
    enumIndex += 1
    enumCase = IterateEnum.item(index: enumIndex)
    if let eCase = enumCase {
        print("The number \(eCase) in french: \(eCase.value.french), spanish: \(eCase.value.spanish), japanese: \(eCase.value.japanese)")
    }
} while enumCase != nil

print("Total of \(enumIndex) cases")

let number = IterateEnum.numberFromSpanish(number: "siete")

print("siete in japanese: \((number?.value.japanese ?? "Unknown"))")

এটি আউটপুট:

ফরাসী ভাষায় শূন্য সংখ্যা: জেরো, স্প্যানিশ: সেরো, জাপানি: নুরু
ফরাসি এক নম্বরে: আন, স্প্যানিশ: উনো, জাপানি: ichi
ফরাসি দুই নম্বরে : ডিউक्स , স্প্যানিশ: ডস, জাপানি: নী
ফরাসি তে তিন নম্বর : ট্রয়স, স্প্যানিশ: ট্রেস, জাপানি: সান
ফরাসি ফোর চার নম্বর: কোয়াটার, স্প্যানিশ: কিয়াতরো, জাপানি: শি
ফরাসি ভাষায় পাঁচ নম্বর: সিনক, স্প্যানিশ: সিনকো, জাপানি: যান
নম্বরে ফরাসি: ছয়, স্প্যানিশ: seis, জাপানি: রাকু
ফরাসি সাত নম্বর: সেপ্ট, স্প্যানিশ: siete, জাপানি: শিচি

মোট ৮ টি মামলা

জাপানি মধ্যে siete: শিচি


হালনাগাদ

আমি সম্প্রতি গণনাটি পরিচালনা করার জন্য একটি প্রোটোকল তৈরি করেছি। প্রোটোকলের জন্য একটি আন্ত কাঁচা মান সহ একটি এনাম প্রয়োজন:

protocol EnumIteration {

    //Used to iterate enum or otherwise access enum case by index order. Iterate by looping until it returns nil

    static func item(index:Int) -> Self?
    static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {
    static func findItem(predicate:((enumCase:Self)->Bool)) -> Self?
    static func count() -> Int
}

extension EnumIteration where Self: RawRepresentable, Self.RawValue == Int {

    //Used to iterate enum or otherwise access enum case by index order. Iterate by looping until it returns nil
    static func item(index:Int) -> Self? {
        return Self.init(rawValue: index)
    }

    static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {

        var enumIndex:Int = -1
        var enumCase:Self?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)

            if let eCase = enumCase {
                item(index: enumIndex, enumCase: eCase)
            }
        } while enumCase != nil
        completion?()
    }

    static func findItem(predicate:((enumCase:Self)->Bool)) -> Self? {

        var enumIndex:Int = -1
        var enumCase:Self?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)

            if let eCase = enumCase {

                if predicate(enumCase:eCase) {
                    return eCase
                }
            }
        } while enumCase != nil
        return nil
    }

    static func count() -> Int {
        var enumIndex:Int = -1
        var enumCase:Self?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)
        } while enumCase != nil

        //last enumIndex (when enumCase == nil) is equal to the enum count
        return enumIndex
    }
}

2

এটি হ্যাকের মতো মনে হয় তবে আপনি যদি কাঁচা মান ব্যবহার করেন তবে আপনি এটির মতো কিছু করতে পারেন

enum Suit: Int {  
    case Spades = 0, Hearts, Diamonds, Clubs  
 ...  
}  

var suitIndex = 0  
while var suit = Suit.fromRaw(suitIndex++) {  
   ...  
}  

2

Swift 2.0এখানে ডিল করার সময় আমার পরামর্শ:

আমি কাঁচা টাইপ যুক্ত করেছি Suit enum

enum Suit: Int {

তারপর:

struct Card {
    var rank: Rank
    var suit: Suit


    func fullDeck()-> [Card] {

        var deck = [Card]()

        for i in Rank.Ace.rawValue...Rank.King.rawValue {

            for j in Suit.Spades.rawValue...Suit.Clubs.rawValue {

                deck.append(Card(rank:Rank(rawValue: i)! , suit: Suit(rawValue: j)!))
            }
        }

        return deck
    }
}

2

এখানে যেমন @ কামেট্রিক্সম উত্তর রয়েছে আমি বিশ্বাস করি যে অ্যারে ফিরিয়ে দেওয়া যেকোন সিক্যুইয়েন্স ফেরানোর চেয়ে ভাল হবে, যেহেতু আপনি অ্যারের সমস্ত গুডি যেমন গণনা ইত্যাদিতে অ্যাক্সেস পেতে পারেন believe

এখানে আবার লিখুন:

public protocol EnumCollection : Hashable {}
extension EnumCollection {
    public static func allValues() -> [Self] {
        typealias S = Self
        let retVal = AnySequence { () -> AnyGenerator<S> in
            var raw = 0
            return AnyGenerator {
                let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }

        return [S](retVal)
    }
}

2

আরেকটি সমাধান:

enum Suit: String {
    case spades = "♠"
    case hearts = "♥"
    case diamonds = "♦"
    case clubs = "♣"

    static var count: Int {
        return 4   
    }

    init(index: Int) {
        switch index {
            case 0: self = .spades
            case 1: self = .hearts
            case 2: self = .diamonds
            default: self = .clubs
        }
    }
}

for i in 0..<Suit.count {
    print(Suit(index: i).rawValue)
}

2

এটি সুইফট ২.০ থেকে একটি পুরানো পোস্ট। এখানে এখন আরও কিছু ভাল সমাধান রয়েছে যা সুইফট 3.0 এর নতুন বৈশিষ্ট্যগুলি ব্যবহার করে: সুইম্ট 3.0 এ এনামের মাধ্যমে আইট্রেটিং

এবং এই প্রশ্নের উপর একটি সমাধান রয়েছে যা একটি নতুন বৈশিষ্ট্য ব্যবহার করে (আমি এই সম্পাদনাটি লেখার সাথে সাথে এখনও প্রকাশিত হয়নি) সুইফট ৪.২: আমি কীভাবে একটি সুইফট এনামের গণনা পেতে পারি?


এই থ্রেড এবং অন্যান্যগুলিতে অনেকগুলি ভাল সমাধান রয়েছে তবে সেগুলির কয়েকটি খুব জটিল। আমি যতটা সম্ভব সহজ করতে চাই like এখানে একটি সমাধান রয়েছে যা বিভিন্ন প্রয়োজনের জন্য কাজ করতে পারে বা নাও পারে তবে আমি মনে করি এটি বেশিরভাগ ক্ষেত্রেই ভাল কাজ করে:

enum Number: String {
    case One
    case Two
    case Three
    case Four
    case EndIndex

    func nextCase () -> Number
    {
        switch self {
        case .One:
            return .Two
        case .Two:
            return .Three
        case .Three:
            return .Four
        case .Four:
            return .EndIndex

        /* 
        Add all additional cases above
        */
        case .EndIndex:
            return .EndIndex
        }
    }

    static var allValues: [String] {
        var array: [String] = Array()
        var number = Number.One

        while number != Number.EndIndex {
            array.append(number.rawValue)
            number = number.nextCase()
        }
        return array
    }
}

পুনরাবৃত্তি করতে:

for item in Number.allValues {
    print("number is: \(item)")
}

1
এটি আপনার অনেকগুলি কাজের মতো মনে হয়েছে যা আপনি তৈরি করেছেন এমন এনামের সাথে সুনির্দিষ্ট - আমি নিশ্চিত নই যে এই [প্রত্যাশা.ওন.রাভভ্যালু, নাম্বার। টু.রাউভ্যালু, ...] ক্লিনার নয়, এক্ষেত্রে ।
স্কট অস্টিন

এটি সুইফট ২.০ থেকে একটি পুরানো পোস্ট। এখানে এখন আরও কয়েকটি আরও ভাল সমাধান রয়েছে যেগুলি সুইফট ৩.০-এর নতুন বৈশিষ্ট্যগুলি ব্যবহার করে: stackoverflow.com/questions/41352594/… এবং এই প্রশ্নের উপর একটি সমাধান রয়েছে যা একটি নতুন বৈশিষ্ট্য ব্যবহার করে (যদিও আমি এই সম্পাদনাটি লিখছি তাই প্রকাশিত হয়নি) ) সুইফট 4.2: স্ট্যাকওভারফ্লো.com
অ্যাবে জ্যাকসন

2

Enums আছে toRaw()এবং fromRaw()পদ্ধতি। সুতরাং আপনার কাঁচা মান যদি একটি হয় তবে Intআপনি প্রথম থেকে শেষ পর্যন্ত পুনরাবৃত্তি করতে পারেন enum:

enum Suit: Int {
    case Spades = 1
    case Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "diamonds"
        case .Clubs:
            return "clubs"
        }
    }
}

for i in Suit.Spades.toRaw()...Suit.Clubs.toRaw() {
    if let covertedSuit = Suit.fromRaw(i) {
        let description = covertedSuit.simpleDescription()
    }
}

একটি গ্যাচা হ'ল simpleDescriptionপদ্ধতিটি চালানোর আগে আপনাকে alচ্ছিক মানগুলির পরীক্ষা করতে হবে , তাই আমরা convertedSuitপ্রথমে আমাদের মানটিতে সেট করেছিলাম এবং তারপরে একটি ধ্রুবক সেট করিconvertedSuit.simpleDescription()


2
মূল প্রশ্নটি ছিল একটি স্ট্রিং টাইপ
এনাম

2

এখানে আমার প্রস্তাবিত পদ্ধতি। এটি সম্পূর্ণ সন্তোষজনক নয় (আমি সুইফ্ট এবং ওওপিতে খুব নতুন!) তবে সম্ভবত কেউ এটিকে পরিমার্জন করতে পারে। ধারণাটি হ'ল প্রতিটি এনামকে তার নিজস্ব পরিসীমা সম্পর্কিত তথ্য .firstএবং .lastবৈশিষ্ট্য সরবরাহ করতে হবে। এটি প্রতিটি এনুমে কোডের দুটি মাত্র লাইন যুক্ত করে: এখনও কিছুটা শক্ত কোডড, তবে কমপক্ষে এটি পুরো সেটটিকে সদৃশ করে না। এটি Suitএনপকে টাইপ না করে Rankএনামের মতো এনট হওয়ার মতো এনামকে সংশোধন করতে হবে ।

পুরো সমাধানটির প্রতিধ্বনি পরিবর্তে, এখানে .এনামগুলিতে আমি যুক্ত কোডটি দিয়েছি , কেস স্টেটমেন্টের পরে কোথাও ( Suitএনাম একই রকম):

var first: Int { return Ace.toRaw() }
var last: Int { return King.toRaw() }

এবং লুপটি আমি স্ট্রিংয়ের অ্যারে হিসাবে ডেক তৈরি করতে ব্যবহার করি। (সমস্যার সংজ্ঞাটি জানায়নি যে ডেকটি কীভাবে গঠন করা হবে))

func createDeck() -> [String] {
    var deck: [String] = []
    var card: String
    for r in Rank.Ace.first...Rank.Ace.last {
        for s in Suit.Hearts.first...Suit.Hearts.last {
            card = Rank.simpleDescription( Rank.fromRaw(r)!)() + " of " + Suit.simpleDescription( Suit.fromRaw(s)!)()
           deck.append( card)
       }
    }
    return deck
}

এটি অসন্তুষ্টিজনক কারণ সম্পত্তিগুলি এনামের পরিবর্তে কোনও উপাদানের সাথে সম্পর্কিত। তবে এটি 'ফর' লুপগুলিতে স্পষ্টতা যুক্ত করে। আমি এটি Rank.firstপরিবর্তে বলতে চাইRank.Ace.first । এটি (যে কোনও উপাদান সহ) কাজ করে তবে এটি কুৎসিত। কেউ এনাম স্তরে কীভাবে উন্নতি করতে পারে তা দেখাতে পারে?

এবং এটি কাজ করতে, আমি createDeckকার্ড কাঠামো থেকে পদ্ধতিটি উত্তোলন করেছি । কীভাবে [স্ট্রিং] অ্যারেটি সেই স্ট্রাক্ট থেকে ফিরে আসবেন তা আমি বুঝতে পারি না এবং যাইহোক এই পদ্ধতিটি রাখার জন্য এটি একটি খারাপ জায়গা বলে মনে হচ্ছে।


2

আমি এটি গণিত সম্পত্তি ব্যবহার করে করেছি, যা সমস্ত মানের অ্যারে প্রদান করে (এই পোস্টটির জন্য ধন্যবাদ http://natecook.com/blog/2014/10/loopy-random-enum-ideas/ )। যাইহোক, এটি অন্তর্গত কাঁচা-মানগুলিও ব্যবহার করে তবে আমার গণনার সমস্ত সদস্যকে পৃথক সম্পত্তিতে পুনরাবৃত্তি করার দরকার নেই।

আপডেট এক্সকোড 6.1 কীভাবে এনাম সদস্য ব্যবহার করবেন তা কিছুটা বদলেছে rawValue, তাই আমি তালিকাটি স্থির করেছি। প্রথমে ভুলের সাথে ছোট ত্রুটিও ঠিক করা হয়েছে rawValue

enum ValidSuits: Int {
    case Clubs = 0, Spades, Hearts, Diamonds
    func description() -> String {
        switch self {
        case .Clubs:
            return "♣︎"
        case .Spades:
            return "♠︎"
        case .Diamonds:
            return "♦︎"
        case .Hearts:
            return "♥︎"
        }
    }

    static var allSuits: [ValidSuits] {
        return Array(
            SequenceOf {
                () -> GeneratorOf<ValidSuits> in
                var i=0
                return GeneratorOf<ValidSuits> {
                    return ValidSuits(rawValue: i++)
                }
            }
        )
    }
}

1
enum Rank: Int
{
    case Ace = 0
    case Two, Three, Four, Five, Six, Seve, Eight, Nine, Ten
    case Jack, Queen, King
    case Count
}

enum Suit : Int
{
    case Spades = 0
    case Hearts, Diamonds, Clubs
    case Count
}

struct Card
{
    var rank:Rank
    var suit:Suit
}

class Test
{
    func makeDeck() -> Card[]
    {
        let suitsCount:Int = Suit.Count.toRaw()
        let rankCount:Int = Rank.Count.toRaw()
        let repeatedCard:Card = Card(rank:Rank.Ace, suit:Suit.Spades)
        let deck:Card[] = Card[](count:suitsCount*rankCount, repeatedValue:repeatedCard)

        for i:Int in 0..rankCount
        {
            for j:Int in 0..suitsCount
            {
                deck[i*suitsCount+j] = Card(rank: Rank.fromRaw(i)!, suit: Suit.fromRaw(j)!)
            }
        }
        return deck
    }
}

রিক উত্তরের ভিত্তিতে: এটি 5 গুণ দ্রুত


একটি Countকেস যুক্ত করা সম্পূর্ণ switchবাস্তবায়ন এবং CaseIterableকনফার্মেশনটি ভেঙে দেবে ।
Cœur
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.