আমি কীভাবে একটি সুইফট এনামের গণনা পেতে পারি?


186

আমি কীভাবে সুইফট এনামের ক্ষেত্রে সংখ্যা নির্ধারণ করতে পারি?

(আমি সমস্ত মানগুলির মধ্যে ম্যানুয়ালি গণনা করা বা যদি সম্ভব হয় তবে পুরানো " এনাম_কাউন্ট ট্রিক " ব্যবহার করা এড়াতে চাই ))

উত্তর:


173

সুইফট ৪.২ (এক্সকোড 10) হিসাবে আপনি CaseIterableপ্রোটোকলে কনফরমেশন ঘোষণা করতে পারেন , এটি সম্পর্কিত মান ব্যতীত সমস্ত গণনার জন্য কাজ করে:

enum Stuff: CaseIterable {
    case first
    case second
    case third
    case forth
}

মামলার সংখ্যা এখন সহজভাবে পাওয়া যায়

print(Stuff.allCases.count) // 4

আরও তথ্যের জন্য, দেখুন


1
সুইফ্টের সর্বশেষ সংস্করণে, এর নিক্ষেপ ত্রুটি "টাইপ 'ডিএএফফ্লো' 'কাঁচা প্রতিস্থাপনযোগ্য'" প্রোটোকলের সাথে খাপ খায় না। আমার কেন তা অনুসরণ করতে বাধ্য করা হচ্ছে? কোন ধারণা?
সত্যম

@ সত্যম: ডিএএফফ্লো কী?
মার্টিন আর

দুঃখিত আমি উল্লেখ করতে ভুলে গেছি যে "ডিএএফএফ্লো" একটি সাধারণ এনাম যা অন্য কোনও প্রোটোকল থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় না
সত্যম

1
এটি সর্বোত্তম সমাধান, তবে কেবল স্পষ্টতার জন্য - অ্যাপল বিকাশকারীরা কেবলমাত্র এক্সকোড 10 একবার (এবং অতএব সুইফ্ট 4.2) বিটা থেকে বেরিয়ে আসার পরে এটি ব্যবহার শুরু করতে সক্ষম হবে (সম্ভবত 14 ই সেপ্টেম্বর 2018 এর আশেপাশে)।
জোসেফ এইচ 5'18

1
@ ডানিস্প্রিঞ্জার: আপনি github.com/apple/swift-evolution/blob/master/proposals/…বেহাল বিবরণ পাবেন । কম্পাইলারের স্বয়ংক্রিয় টাইপের অনুক্রমের কারণে সাধারণত আপনার স্পষ্টভাবে ধরণের প্রয়োজন হয় না।
মার্টিন আর

143

আমার একটি ব্লগ পোস্ট রয়েছে যা এটি সম্পর্কে আরও বিশদে যায় তবে যতক্ষণ না আপনার এনামের কাঁচা টাইপ পূর্ণসংখ্যার হয় ততক্ষণ আপনি এইভাবে একটি গণনা যুক্ত করতে পারেন:

enum Reindeer: Int {
    case Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen
    case Rudolph

    static let count: Int = {
        var max: Int = 0
        while let _ = Reindeer(rawValue: max) { max += 1 }
        return max
    }()
}

16
যদিও দুর্দান্ত কারণ আপনার কোনও মানকে হার্ডকোড দেওয়ার দরকার নেই, এটি প্রতিবার যখন এনামকে বলা হয় তখন এটি তাত্ক্ষণিকভাবে প্রেরণ করবে। ও (1) এর পরিবর্তে ও (এন)। :(
কোড কমান্ডার

4
এটি সংহত ইন্টের জন্য একটি ভাল সমাধান। আমি সামান্য পরিবর্তন পছন্দ করি। স্ট্যাটিক কাউন্ট সম্পত্তিটি একটি স্ট্যাটিক মেথড কাউন্টক্যাসে পরিণত করুন () এবং এটি একটি স্ট্যাটিক ধ্রুবক কেসকাউন্টে অর্পণ করুন যা অলস এবং বারবার কলগুলির সাথে কার্যকারিতা উন্নত করে।
টম পেলাইয়া

2
@ শামসাহেমেড: গণিত ভারকে একটি স্ট্যাটিক রূপান্তরিত।
নাট কুক

3
এনামে কিছু মূল্য মিস করলে কী হবে? যেমন case A=1, B=3?
সাশো

2
আপনি উল্লেখ করতে ভুলে গেছেন এমন enumএকটি Intকাঁচা মান থাকা ছাড়াও দুটি অনুমান রয়েছে : সুইট এনামের সাথে ইন্ট কাঁচা মানগুলি 0 থেকে শুরু করতে হবে না (যদিও এটি ডিফল্ট আচরণ) এবং তাদের কাঁচা মানগুলি নির্বিচারে হতে পারে, তাদের নেই 1 দ্বারা বৃদ্ধি করা (যদিও এটি ডিফল্ট আচরণ)।
ডেভিড পাসস্টর

90

এক্সকোড 10 আপডেট

এনামে CaseIterableপ্রোটোকল গ্রহণ করুন , এটি একটি স্ট্যাটিক allCasesসম্পত্তি সরবরাহ করে যা সমস্ত এনাম কেস হিসাবে অন্তর্ভুক্ত করে Collectioncountএনামের কতগুলি মামলা রয়েছে তা জানতে কেবল তার সম্পত্তিটি ব্যবহার করুন ।

উদাহরণের জন্য মার্টিনের উত্তর দেখুন (এবং আমার উত্তর না দিয়ে তার উত্তরগুলি অগ্রাহ্য করুন)


সতর্কতা : নীচের পদ্ধতিটি আর কাজ করবে বলে মনে হচ্ছে না।

এনাম কেসের সংখ্যা গণনা করার জন্য আমি কোনও জেনেরিক পদ্ধতি সম্পর্কে অবগত নই। তবে আমি লক্ষ করেছি যে hashValueএনামের মামলার সম্পত্তি ক্রমবর্ধমান, শূন্য থেকে শুরু হয়ে, এবং আদেশগুলি নির্ধারিত আদেশের সাথে মামলাগুলি ঘোষিত হয়। সুতরাং, সর্বশেষ এনাম প্লাস ওয়ানের হ্যাশ মামলার সংখ্যার সাথে মিলে যায়।

উদাহরণস্বরূপ এই এনাম সহ:

enum Test {
    case ONE
    case TWO
    case THREE
    case FOUR

    static var count: Int { return Test.FOUR.hashValue + 1}
}

count 4 রিটার্ন

আমি এটি বলতে পারি না এটি যদি একটি নিয়ম হয় বা ভবিষ্যতে যদি কখনও পরিবর্তিত হয় তবে আপনার নিজের ঝুঁকিতে ব্যবহার করুন :)


48
অননুমোদিত বৈশিষ্ট্য দ্বারা লাইভ, অননুমোদিত বৈশিষ্ট্য দ্বারা মারা যান। আমি এটা পছন্দ করি!
নেট কুক

9
আমাদের সত্যিকার অর্থে hashValuesএই বিষয়ের উপর নির্ভর করা উচিত নয় ; আমরা কেবল জানি এটি কিছু এলোমেলো অনন্য মূল্য - কিছু সংকলক বাস্তবায়নের বিশদের উপর নির্ভর করে ভবিষ্যতে খুব সহজেই পরিবর্তন হতে পারে; তবে সামগ্রিকভাবে, বিল্ট-ইন গণনা কার্যকারিতার অভাব বিরক্তিকর।
জোড়ায়র

16
আপনি যদি সুস্পষ্টভাবে সেটিংস করতে আপত্তি case ONE = 0না করেন তবে আপনি এটির hashValueসাথে প্রতিস্থাপন করতে পারেন rawValue
কেভিন কিউ

3
এখানে উদ্বেগ হ্যাশভ্যালুয়ের একটি অননুমোদিত সম্পত্তি ব্যবহার, সুতরাং আমার পরামর্শটি কাঁচাভ্যালুতে একটি নথিভুক্ত সম্পত্তি ব্যবহার করার জন্য।
কেভিন কিউ

7
আপনি ইতিমধ্যে এই সত্যটিকে শক্ত করে static var count = 4গেছেন যে ধ্রুবকটি সর্বোচ্চ মান, আরও ভাল এবং নিরাপদ ভবিষ্যতের সুইফ্টের বাস্তবায়নের ভাগ্যে নিজের ভাগ্য ছেড়ে যাওয়ার পরিবর্তে এমন কিছু ব্যবহার করা নিরাপদ
ডেল

72

আমি একটি পুনরায় ব্যবহারযোগ্য প্রোটোকল সংজ্ঞায়িত করেছি যা নাট কুক দ্বারা পোস্ট করা পদ্ধতির ভিত্তিতে স্বয়ংক্রিয়ভাবে কেস গণনা সম্পাদন করে।

protocol CaseCountable {
    static var caseCount: Int { get }
}

extension CaseCountable where Self: RawRepresentable, Self.RawValue == Int {
    internal static var caseCount: Int {
        var count = 0
        while let _ = Self(rawValue: count) {
            count += 1
        }
        return count
    }
}

তারপরে আমি উদাহরণস্বরূপ এই প্রোটোকলটি পুনরায় ব্যবহার করতে পারি:

enum Planet : Int, CaseCountable {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//..
print(Planet.caseCount)

1
সুন্দর এবং মার্জিত, গ্রহণযোগ্য উত্তর হওয়া উচিত
IMHO

1
সম্ভবত বদলে count++যাওয়া আরও ভাল হয় count+=1যেহেতু ++স্বরলিপিটি সুইফট 3
আলাদিনে

1
একই সঙ্গে কি করা যায় না শুধুমাত্র static var caseCount: Int { get }? কেন প্রয়োজন static func?
pxpographicics

এনামে কিছু মূল্য মিস করলে কী হবে? যেমন case A=1, B=3?
সাশো

1
@ সাশো, তাহলে এটি কার্যকর হবে না। এটির জন্য আপনার কেসগুলি শুরু হওয়া দরকার 0এবং কোনও ফাঁক নেই।
NRitH

35

এই উত্তরে প্রদর্শিত হিসাবে স্থিতিশীল অলভ্যালু অ্যারে তৈরি করুন

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

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

...

let count = ProductCategory.allValues.count

আপনি যখন মানগুলি গণনা করতে চান এবং সমস্ত এনুম ধরণের জন্য কাজ করেন তখন এটিও সহায়ক


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

2
আপনি এনামে গণনাটি যোগ করেও করতে পারেন static let count = allValues.count। তারপরে আপনি চাইলে allValuesব্যক্তিগত করতে পারেন make
টমাসডাব্লু

15

যদি বাস্তবায়নের পূর্ণসংখ্যার এনামগুলি ব্যবহারের বিরুদ্ধে কিছু না থাকে তবে আপনি এনামে সদস্য Countসংখ্যা উপস্থাপনের জন্য ডাকা অতিরিক্ত সদস্যের মান যুক্ত করতে পারেন - নীচের উদাহরণটি দেখুন:

enum TableViewSections : Int {
  case Watchlist
  case AddButton
  case Count
}

এখন আপনি কল করে এনামে সদস্য সংখ্যা পেতে পারেন, TableViewSections.Count.rawValueযা উপরের উদাহরণের জন্য 2 ফিরে আসবে।

আপনি যখন একটি স্যুইচ স্টেটমেন্টে এনামকে পরিচালনা করছেন, এমন Countসদস্যের মুখোমুখি হওয়ার সময় আপনি যখন এটি আশা করেন না তখন তার প্রতিরোধের ব্যর্থতা ফেলে দেওয়ার বিষয়টি নিশ্চিত করুন :

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let currentSection: TableViewSections = TableViewSections.init(rawValue:section)!
  switch(currentSection) {
  case .Watchlist:
    return watchlist.count
  case .AddButton:
    return 1
  case .Count:
    assert(false, "Invalid table view section!")
  }
}

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

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

3
আমি ভেবেছিলাম সুইফ্টের আরও শক্তিশালী এনামগুলির পুরো বিষয়টি হ'ল আমাদের উদ্দেশ্য
হ'ল

14

এই জাতীয় ফাংশন আপনার এনামের গণনা ফিরিয়ে দিতে সক্ষম।

সুইফট 2 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(&i) { UnsafePointer<T>($0).memory }).hashValue != 0 {
        i += 1
    }
    return i
}

সুইফট 3 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
   var i = 1
   while (withUnsafePointer(to: &i, {
      return $0.withMemoryRebound(to: T.self, capacity: 1, { return $0.pointee })
   }).hashValue != 0) {
      i += 1
   }
      return i
   }

3
এটি আর সুইফট 3 এর জন্য কাজ করে না যথাযথ প্রয়োগের জন্য চেষ্টা করার চেষ্টা করে, কিন্তু খালি আসবে
কোডি উইন্টন ২

এই ডিবাগ করা খুব unfun হতে হবে মেমরি অ্যাড্রেস অবিলম্বে শেষে সংলগ্ন যদি enumহয় এছাড়াও Hashable একই ধরণের।
NRitH

10

সূচি সহ স্ট্রিং এনুম

enum eEventTabType : String {
    case Search     = "SEARCH"
    case Inbox      = "INBOX"
    case Accepted   = "ACCEPTED"
    case Saved      = "SAVED"
    case Declined   = "DECLINED"
    case Organized  = "ORGANIZED"

    static let allValues = [Search, Inbox, Accepted, Saved, Declined, Organized]
    var index : Int {
       return eEventTabType.allValues.indexOf(self)!
    }
}

গণনা: eEventTabType.allValues.count

সূচক: objeEventTabType.index

উপভোগ করুন :)


10

ওহে সবাই, ইউনিট পরীক্ষার কি হবে?

func testEnumCountIsEqualToNumberOfItemsInEnum() {

    var max: Int = 0
    while let _ = Test(rawValue: max) { max += 1 }

    XCTAssert(max == Test.count)
}

এটি অ্যান্টোনিওর সমাধানের সাথে মিলিত হয়েছে:

enum Test {

    case one
    case two
    case three
    case four

    static var count: Int { return Test.four.hashValue + 1}
}

মূল কোডটি আপনাকে ও (1) দেয় এবং যদি কোনও এনাম কেস যুক্ত করে এবং এর প্রয়োগ আপডেট না করে তবে আপনি ব্যর্থ পরীক্ষাfive পান count


7

এই ফাংশনটি 2 অননুমোদিত বর্তমান (সুইফট 1.1) enumআচরণের উপর নির্ভর করে :

  • এর মেমরি লেআউটটি enumকেবল একটি সূচক case। যদি কেস গণনা 2 থেকে 256 পর্যন্ত হয় তবে তা UInt8
  • যদি অবৈধ কেস সূচক enumথেকে বিট-কাস্ট করা হয় তবে তাhashValue0

সুতরাং আপনার নিজের ঝুঁকিতে ব্যবহার করুন :)

func enumCaseCount<T:Hashable>(t:T.Type) -> Int {
    switch sizeof(t) {
    case 0:
        return 1
    case 1:
        for i in 2..<256 {
            if unsafeBitCast(UInt8(i), t).hashValue == 0 {
                return i
            }
        }
        return 256
    case 2:
        for i in 257..<65536 {
            if unsafeBitCast(UInt16(i), t).hashValue == 0 {
                return i
            }
        }
        return 65536
    default:
        fatalError("too many")
    }
}

ব্যবহার:

enum Foo:String {
    case C000 = "foo"
    case C001 = "bar"
    case C002 = "baz"
}
enumCaseCount(Foo) // -> 3

রিলিজ এবং অ্যাডহক অ্যাপ্লিকেশনটি ক্র্যাশ করবে
হটজার্ড

এটি সিমুলেটারে কাজ করে তবে আসল bit৪ বিট ডিভাইসে নয়।
ড্যানিয়েল নর্ড

5

আমি একটি সাধারণ এক্সটেনশন লিখেছিলাম যা সমস্ত এনামগুলিকে দেয় যেখানে কাঁচা মান একটি সংখ্যার countসম্পত্তি হয়:

extension RawRepresentable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

দুর্ভাগ্যক্রমে এটি countসম্পত্তিটি OptionSetTypeযেখানে এটি যথাযথভাবে কাজ করবে না তা দেয় , সুতরাং এখানে এমন আরও একটি সংস্করণ রয়েছে যার CaseCountableকোনও প্রকারের এনটামের জন্য প্রোটোকলের স্পষ্ট ধারণা প্রয়োজন যা আপনি গণনা করতে চান:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

এটি টম পেলেয়ার পোস্ট করা পদ্ধতির সাথে খুব মিল, তবে সমস্ত পূর্ণসংখ্যার ধরণের সাথে কাজ করে।


4

অবশ্যই, এটি গতিশীল নয় তবে অনেকগুলি ব্যবহারের জন্য আপনি আপনার এনামে একটি স্ট্যাটিক ভার যোগ করতে পারেন

static var count: Int{ return 7 }

এবং তারপরে এটি ব্যবহার করুন EnumName.count


3
enum EnumNameType: Int {
    case first
    case second
    case third

    static var count: Int { return EnumNameType.third.rawValue + 1 }
}

print(EnumNameType.count) //3

অথবা

enum EnumNameType: Int {
    case first
    case second
    case third
    case count
}

print(EnumNameType.count.rawValue) //3

* সুইফটে 4.2 এ (এক্সকোড 10) ব্যবহার করতে পারেন:

enum EnumNameType: CaseIterable {
    case first
    case second
    case third
}

print(EnumNameType.allCases.count) //3

2

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

উপরের উত্তরগুলির মধ্যে কয়েকটি সুইফট 2 এ অর্জনের উপায় দেখায় তবে কোনওটি সুইফ্ট 3-তে কাজ করে না । এখানে সুইফট 3 ফর্ম্যাট সংস্করণ:

static func enumCount<T: Hashable>(_ t: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(to: &i) {
      $0.withMemoryRebound(to:t.self, capacity:1) { $0.pointee.hashValue != 0 }
    }) {
      i += 1
    }
    return i
}

static var allKeys: [YourEnumTypeHere] {
    var enumSize = enumCount(YourEnumTypeHere.self)

    let keys: Set<YourEnumTypeHere> = [.all, .your, .cases, .here]
    guard keys.count == enumSize else {
       fatalError("Missmatch between allKeys(\(keys.count)) and actual keys(\(enumSize)) in enum.")
    }
    return Array(keys)
}

আপনার ব্যবহারের ক্ষেত্রে উপর নির্ভর করে, প্রতিটি অনুরোধে AllKeys ব্যবহারের ওভারহেড এড়াতে আপনি কেবল বিকাশের পরীক্ষা চালাতে চাইতে পারেন


2

আপনি এগুলি এত জটিল করে তুলছেন কেন? ইন্ট এনামের সিম্প্লেস্ট কাউন্টারটি যুক্ত করতে হবে:

case Count

শেষে. এবং ... ভায়োলা - এখন আপনার গণনা রয়েছে - দ্রুত এবং সহজ


1
এটি ক) একটি বহিরাগত এনাম কেস যুক্ত করে এবং খ) এনামের কাঁচা টাইপ ইন্ট ব্যতীত অন্য কিছু হলে কাজ করবে না।
রবার্ট অ্যাটকিনস

এটি আসলে কোনও খারাপ উত্তর নয়। উপরের @ টম পেলেয়ার উত্তরটির মতো, তবে এটির জন্য কাঁচা মানগুলি শুরু হওয়া দরকার 0এবং ক্রমটির কোনও ফাঁক নেই।
NRitH

1

আপনি যদি সর্বশেষ এনুমে আপনার কোডটি বেস করতে না চান তবে আপনি নিজের এনামের ভিতরে এই ফাংশনটি তৈরি করতে পারেন।

func getNumberOfItems() -> Int {
    var i:Int = 0
    var exit:Bool = false
    while !exit {
        if let menuIndex = MenuIndex(rawValue: i) {
            i++
        }else{
            exit = true
        }
    }
    return i
}

1

টাইপ এনামগুলির সাথে কাজ করা একটি সুইফ্ট 3 সংস্করণ Int:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue == Int {
    static var count: RawValue {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) { i += 1 }
        return i
    }
}

ক্রেডিট: bzz এবং নেট কুকের উত্তরগুলির ভিত্তিতে।

জেনেরিক IntegerType(স্যুইফ্ট 3 এ নতুন নামকরণ করা হয়েছে Integer) সমর্থিত নয়, কারণ এটি একটি বিশাল আকারের খণ্ডিত জেনেরিক ধরণের যা অনেকগুলি ফাংশনের অভাবে। successorসুইফট 3 এর সাথে আর পাওয়া যায় না।

নোট কুক্সের উত্তর কোড কমান্ডার থেকে দেওয়া মন্তব্যটি এখনও বৈধ: এ বিষয়ে সচেতন থাকুন

যদিও দুর্দান্ত কারণ আপনার কোনও মানকে হার্ডকোড দেওয়ার দরকার নেই, এটি প্রতিবার যখন এনামকে বলা হয় তখন এটি তাত্ক্ষণিকভাবে প্রেরণ করবে। ও (1) এর পরিবর্তে ও (এন)।

যতদূর আমি জানি যে প্রোটোকল এক্সটেনশন হিসাবে ব্যবহার করার সময় বর্তমানে কোনও কার্যকারিতা নেই (এবং ন্যাট কুকের মতো প্রতিটি এনামে প্রয়োগ করা হয়নি) স্থির স্টোরেজ বৈশিষ্ট্যগুলি জেনেরিক ধরণের ক্ষেত্রে সমর্থনযোগ্য নয় বলে।

যাইহোক, ছোট এনামগুলির জন্য এটি কোনও সমস্যা হওয়া উচিত নয়। একটা প্রচলিত ব্যবহারের ক্ষেত্রে হবে section.countজন্য UITableViewsইতিমধ্যে Zorayr দ্বারা হিসাবে উল্লেখ করেছে।


1

ম্যাথিয়েইউ রিগেলার উত্তর প্রসারিত করা, এটি সুইফট 3 এর জন্য একটি সমাধান যা জেনেরিক ব্যবহারের প্রয়োজন হয় না এবং এনাম টাইপ ব্যবহার করে সহজেই এটি কল করা যেতে পারে EnumType.elementsCount:

extension RawRepresentable where Self: Hashable {

    // Returns the number of elements in a RawRepresentable data structure
    static var elementsCount: Int {
        var i = 1
        while (withUnsafePointer(to: &i, {
            return $0.withMemoryRebound(to: self, capacity: 1, { return 
                   $0.pointee })
        }).hashValue != 0) {
            i += 1
        }
        return i
}

0

আমি এই সমস্যাটি সমাধান করেছিলাম একটি প্রোটোকল (এনামআইন্টআর্রে) এবং একটি বিশ্বব্যাপী ইউটিলিটি ফাংশন (enumIntArray) তৈরি করে যা কোনও এনামের সাথে "সমস্ত" পরিবর্তনশীল যুক্ত করা খুব সহজ করে তোলে (সুইফট 1.2 ব্যবহার করে)। "সমস্ত" ভেরিয়েবলটিতে এনামের সমস্ত উপাদানগুলির একটি অ্যারে থাকবে যাতে আপনি গণনার জন্য all.count ব্যবহার করতে পারেন

এটি কেবল এনামের সাথে কাজ করে যা টাইপ ইন্টের কাঁচা মান ব্যবহার করে তবে সম্ভবত এটি অন্যান্য ধরণের জন্য কিছু অনুপ্রেরণা সরবরাহ করতে পারে।

এটি উপরে এবং অন্য কোথাও পড়ে থাকা "সংখ্যার ফাঁক" এবং "পুনরাবৃত্তি করার জন্য অতিরিক্ত সময়" সম্পর্কিত বিষয়গুলিও সম্বোধন করে।

ধারণাটি হ'ল EnumIntArray প্রোটোকলটি আপনার enum এ যুক্ত করুন এবং তারপরে EnumIntArray ফাংশনটি কল করে একটি "সমস্ত" স্ট্যাটিক ভেরিয়েবল সংজ্ঞায়িত করুন এবং প্রথম উপাদানটি সরবরাহ করুন (এবং সংখ্যার ফাঁক থাকলে শেষটি)।

স্ট্যাটিক ভেরিয়েবলটি কেবল একবার শুরু করার কারণে, সমস্ত কাঁচা মানগুলি অতিক্রম করার ওভারহেড কেবল একবার আপনার প্রোগ্রামকে হিট করে।

উদাহরণ (ফাঁক ছাড়াই):

enum Animals:Int, EnumIntArray
{ 
  case Cat=1, Dog, Rabbit, Chicken, Cow
  static var all = enumIntArray(Animals.Cat)
}

উদাহরণ (ফাঁক দিয়ে):

enum Animals:Int, EnumIntArray
{ 
  case Cat    = 1,  Dog, 
  case Rabbit = 10, Chicken, Cow
  static var all = enumIntArray(Animals.Cat, Animals.Cow)
}

এখানে কোড প্রয়োগ করা হয়েছে যা এটি প্রয়োগ করে:

protocol EnumIntArray
{
   init?(rawValue:Int)
   var rawValue:Int { get }
}

func enumIntArray<T:EnumIntArray>(firstValue:T, _ lastValue:T? = nil) -> [T]
{
   var result:[T] = []
   var rawValue   = firstValue.rawValue
   while true
   { 
     if let enumValue = T(rawValue:rawValue++) 
     { result.append(enumValue) }
     else if lastValue == nil                     
     { break }

     if lastValue != nil
     && rawValue  >  lastValue!.rawValue          
     { break }
   } 
   return result   
}

0

অথবা আপনি _countএনামের বাইরের অংশটি সংজ্ঞায়িত করতে পারেন এবং এটি স্থিরভাবে সংযুক্ত করতে পারেন:

let _count: Int = {
    var max: Int = 0
    while let _ = EnumName(rawValue: max) { max += 1 }
    return max
}()

enum EnumName: Int {
    case val0 = 0
    case val1
    static let count = _count
}

আপনি যতগুলি এনাম তৈরি করেন তা সেভাবেই নয়, এটি কেবল একবারই তৈরি হবে।

(যদি staticতা করে তবে এই উত্তরটি মুছুন )


0

নিম্নলিখিত পদ্ধতিটি কোরিকিট থেকে এসেছে এবং অন্য কেউ কেউ জবাব দিয়েছিল তার অনুরূপ। এটি সুইফট 4 এর সাথে কাজ করে।

public protocol EnumCollection: Hashable {
    static func cases() -> AnySequence<Self>
    static var allValues: [Self] { get }
}

public extension EnumCollection {

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

    public static var allValues: [Self] {
        return Array(self.cases())
    }
}

enum Weekdays: String, EnumCollection {
    case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}

তারপরে আপনাকে কেবল কল করতে হবে Weekdays.allValues.count


0
enum WeekDays : String , CaseIterable
{
  case monday = "Mon"
  case tuesday = "Tue"
  case wednesday = "Wed"
  case thursday = "Thu"
  case friday = "Fri"
  case saturday = "Sat"
  case sunday = "Sun"
}

var weekdays = WeekDays.AllCases()

print("\(weekdays.count)")

-1
struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }
            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().enumCount
    }
}

enum E {
    case A
    case B
    case C
}

E.enumCases() // [A, B, C]
E.enumCount   //  3

তবে এন-এনাম ধরণের ব্যবহারের বিষয়ে সতর্ক থাকুন। কিছুটা কাজ হতে পারে:

struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            guard sizeof(T) == 1 else {
                return nil
            }
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }

            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().count
    }
}

enum E {
    case A
    case B
    case C
}

Bool.enumCases()   // [false, true]
Bool.enumCount     // 2
String.enumCases() // []
String.enumCount   // 0
Int.enumCases()    // []
Int.enumCount      // 0
E.enumCases()      // [A, B, C]
E.enumCount        // 4

-1

এটি একটি স্ট্যাটিক ধ্রুবক ব্যবহার করতে পারে যার মধ্যে গণনা প্লাস ওজনের শেষ মান থাকে।

enum Color : Int {
    case  Red, Orange, Yellow, Green, Cyan, Blue, Purple

    static let count: Int = Color.Purple.rawValue + 1

    func toUIColor() -> UIColor{
        switch self {
            case .Red:
                return UIColor.redColor()
            case .Orange:
                return UIColor.orangeColor()
            case .Yellow:
                return UIColor.yellowColor()
            case .Green:
                return UIColor.greenColor()
            case .Cyan:
                return UIColor.cyanColor()
            case .Blue:
                return UIColor.blueColor()
            case .Purple:
                return UIColor.redColor()
        }
    }
}

-3

এটি সামান্য, তবে আমি মনে করি আরও ভাল ও (1) সমাধান নিম্নলিখিত হবে ( কেবলমাত্র আপনার এনাম Intএক্স, ইত্যাদি থেকে শুরু হয়):

enum Test : Int {
    case ONE = 1
    case TWO
    case THREE
    case FOUR // if you later need to add additional enums add above COUNT so COUNT is always the last enum value 
    case COUNT

    static var count: Int { return Test.COUNT.rawValue } // note if your enum starts at 0, some other number, etc. you'll need to add on to the raw value the differential 
}

আমি এখনও বিশ্বাস করি যে বর্তমান নির্বাচিত উত্তর হ'ল সমস্ত এনামের পক্ষে সেরা উত্তর, যদি না আপনি Intতখন কাজ করে থাকেন তবে আমি এই সমাধানটি সুপারিশ করি।


3
আপনার এনামে এমন কোনও মান যুক্ত করা যা প্রকৃতপক্ষে এনামের ধরণের প্রতিনিধিত্ব করে না এটি একটি খারাপ কোডের গন্ধ। এমনকি "মাঝে মাঝে লোভনীয় হওয়া সত্ত্বেও" সমস্ত "বা" কিছুই না "সহ যুক্তিসঙ্গত করা আমার পক্ষে কঠিন। এই ইস্যুটি সম্পর্কে হ্যাক করার জন্য একটি "COUNT" অন্তর্ভুক্ত করা খুব দুর্গন্ধযুক্ত।
মাইকেল পিটারসন

1
Stinky? আপনি যদি এটি নিশ্চিত বলতে চান। Performant? হ্যাঁ. এটি উন্নতকারীদের পক্ষে পক্ষে-বিপক্ষে সিদ্ধান্ত নিতে হবে। এটি প্রকৃতপক্ষে জোরায়ের উত্তরের একই উত্তর যেখানে তিনি এটি সম্পর্কে আরও বিশদে যান এবং নতুন গৃহীত উত্তরও একই রকম। তবে যতক্ষণ না দ্রুত তার পক্ষে এপি যোগ করে; আমাদের মধ্যে কিছু এটি ব্যবহার করার সিদ্ধান্ত নিয়েছে। প্রকারের উপস্থাপনের বিষয়ে আপনার উদ্বেগ সমাধান করতে আপনি এমন একটি ক্রিয়া যুক্ত করতে পারেন যা এনাম মানটির guardবিরুদ্ধে বৈধতা COUNTদেয় এবং ত্রুটি ছুড়ে দেয়, মিথ্যা ফিরিয়ে দেয়।
ড্রমরগান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.