কীভাবে অবজেক্টগুলির স্থির-আকারের অ্যারে তৈরি করা যায়


102

সুইফটে, আমি 64 এসকেএসপ্রিটনোডের একটি অ্যারে তৈরি করার চেষ্টা করছি। আমি প্রথমে এটি খালি শুরু করতে চাই, তারপরে আমি স্প্রিটসকে প্রথম 16 কোষে এবং শেষ 16 কোষে (একটি দাবা খেলার অনুকরণে) রাখব।

আমি ডকটিতে যা বুঝলাম সেখান থেকে আমার এমন কিছু আশা করা উচিত:

var sprites = SKSpriteNode()[64];

বা

var sprites4 : SKSpriteNode[64];

কিন্তু এটি কাজ করে না। দ্বিতীয় ক্ষেত্রে, আমি এই বলে একটি ত্রুটি পেয়েছি: "স্থির দৈর্ঘ্যের অ্যারেগুলি এখনও সমর্থিত নয়"। এটা কি বাস্তব হতে পারে? আমার কাছে যা একটি মৌলিক বৈশিষ্ট্য বলে মনে হচ্ছে। আমি তাদের সূচক দ্বারা সরাসরি উপাদান অ্যাক্সেস প্রয়োজন।

উত্তর:


152

স্থির দৈর্ঘ্যের অ্যারেগুলি এখনও সমর্থিত নয়। কি যে আসলে মানে? এমন নয় যে আপনি nঅনেকগুলি অ্যারে তৈরি করতে পারবেন না - স্পষ্টতই আপনি কেবল let a = [ 1, 2, 3 ]তিনটি Intএস এর অ্যারে পেতে পারেন । এর অর্থ হ'ল অ্যারের আকার এমন কিছু নয় যা আপনি টাইপ তথ্য হিসাবে ঘোষণা করতে পারেন ।

আপনি যদি একটি অ্যারে চান তবে nilআপনার প্রথমে একটি alচ্ছিক ধরণের অ্যারের প্রয়োজন - [SKSpriteNode?]না [SKSpriteNode]- আপনি যদি অ-alচ্ছিক প্রকারের ভেরিয়েবল ঘোষণা করেন তবে এটি অ্যারে বা একক মান, তা হতে পারে না nil। (এছাড়াও লক্ষ করুন যে এটির [SKSpriteNode?]চেয়ে আলাদা [SKSpriteNode]?... আপনি ofচ্ছিক অ্যারে নয়, বিকল্পগুলির একটি অ্যারে চান))

ভেরিয়েবলগুলি আরম্ভ করার প্রয়োজনীয়তা সম্পর্কে নকশার মাধ্যমে সুইফ্টটি খুব স্পষ্ট, কারণ অবিচ্ছিন্ন রেফারেন্সের বিষয়বস্তু সম্পর্কে অনুমান একটি উপায় যা সি (এবং কিছু অন্যান্য ভাষায়) প্রোগ্রামগুলিতে বগী হয়ে উঠতে পারে of সুতরাং, আপনাকে স্পষ্টভাবে [SKSpriteNode?]এমন একটি অ্যারের জন্য জিজ্ঞাসা করতে হবে যাতে s৪ টি রয়েছে nil:

var sprites = [SKSpriteNode?](repeating: nil, count: 64)

এটি আসলে একটি প্রদান করে [SKSpriteNode?]?, যদিও: alচ্ছিক স্প্রাইটের একটি alচ্ছিক অ্যারে। (কিছুটা অদ্ভুত, যেহেতু init(count:,repeatedValue:)শূন্যতা ফিরে আসতে সক্ষম হওয়া উচিত নয়)) অ্যারের সাথে কাজ করার জন্য, আপনাকে এটি আবরণ করা দরকার। এটি করার কয়েকটি উপায় রয়েছে তবে এই ক্ষেত্রে আমি alচ্ছিক বাঁধাইয়ের সিনট্যাক্সটির পক্ষে চাই:

if var sprites = [SKSpriteNode?](repeating: nil, count: 64){
    sprites[0] = pawnSprite
}

ধন্যবাদ, আমি এটি চেষ্টা করেছিলাম, তবে আমি "?" ভুলে গিয়েছিলাম। যাইহোক, আমি এখনও মান পরিবর্তন করতে অক্ষম? আমি উভয়ই চেষ্টা করেছি: 1) স্প্রাইট [0] = স্প্রাইটপাউন এবং 2) স্প্রিটস.ইন্রেট (স্প্রাইটপাউন, এন্ডেক্স: 0)।
হেনরি লাপিয়ের

4
আশ্চর্য! spritesএটির অনুমানযুক্ত প্রকারটি দেখতে আপনার সম্পাদক / খেলার মাঠে সিএমডি-ক্লিক করুন - এটি আসলে SKSpriteNode?[]?: alচ্ছিক স্প্রেটের একটি optionচ্ছিক অ্যারে। আপনি একটি subsচ্ছিক সাবস্ক্রিপ্ট করতে পারবেন না, তাই আপনাকে এটি আন-rapেকে ফেলতে হবে ... সম্পাদিত উত্তর দেখুন।
রিক্সার

এটা আসলেই বেশ বিজোড়। যেমনটি আপনি উল্লেখ করেছেন, আমি মনে করি না যে অ্যারেটি beচ্ছিক হওয়া উচিত, কারণ আমরা এটি স্পষ্টভাবে সংজ্ঞায়িত করেছি? []] এবং না? [] ?. আমার যতবার দরকার হয় তা মুছে ফেলার মতো ধরণের বিরক্তিজনক যাইহোক, এটি কাজ করছে বলে মনে হচ্ছে: var sprites = SKSpriteNode? [] (গণনা: ,৪, পুনরাবৃত্তিযোগ্য: শূন্য); if var unwrappedSprite = sprites w unwrapedSprite [0] = spritPawn; }
হেনরি লাপিয়ার 21

সিন্ট্যাক্স 3 এবং 4 এর সুইফ্টের জন্য পরিবর্তিত হয়েছে, দয়া করে নীচের অন্যান্য উত্তরগুলি দেখুন
ক্র্যাশলোট

62

আপাতত আপনি যে সেরাটি করতে সক্ষম হচ্ছেন তা হ'ল পুনরায় পুনরুক্তি শুরুর একটি অ্যারে তৈরি করা:

var sprites = [SKSpriteNode?](count: 64, repeatedValue: nil)

তারপরে আপনি যা মান চান তা পূরণ করতে পারেন।


ইন সুইফট 3.0 :

var sprites = [SKSpriteNode?](repeating: nil, count: 64)

4
নির্দিষ্ট আকারের অ্যারে ঘোষণা করার কোনও উপায় আছে ?
レ ッ ク

4
@ আলেকজান্ডারসুপারট্র্যাম নং, অ্যারের জন্য কোনও আকার ঘোষণার উপায় নেই
ড্রুয়াগ করুন

4
@ ア レ ッ ク an অ্যারের জন্য একটি নির্দিষ্ট আকার ঘোষণা করার কোনও উপায় নেই তবে আপনি অবশ্যই নিজের স্ট্রাক্ট তৈরি করতে পারেন যা একটি অ্যারে আবৃত করে একটি নির্দিষ্ট আকারকে কার্যকর করে।
ড্র্যাগ করুন ag

11

এই প্রশ্নের ইতিমধ্যে উত্তর দেওয়া হয়েছে, তবে সুইফট 4-এর সময়ে অতিরিক্ত তথ্যের জন্য:

পারফরম্যান্সের ক্ষেত্রে, আপনাকে অ্যারের জন্য মেমরি সংরক্ষণ করতে হবে, গতিশীলভাবে তৈরির ক্ষেত্রে যেমন এর সাথে উপাদান যুক্ত করা Array.append()

var array = [SKSpriteNode]()
array.reserveCapacity(64)

for _ in 0..<64 {
    array.append(SKSpriteNode())
}

আপনি যদি ন্যূনতম পরিমাণের উপাদানগুলিতে এটি যোগ করবেন তবে সর্বাধিক পরিমাণ নয়, তবে আপনার ব্যবহার করা উচিত array.reserveCapacity(minimumCapacity: 64)


6

একটি খালি এসকেএসপ্রিটনোড ঘোষণা করুন, সুতরাং আন-র্যাপিংয়ের প্রয়োজন হবে না

var sprites = [SKSpriteNode](count: 64, repeatedValue: SKSpriteNode())

9
এই বিষয়ে সতর্কতা অবলম্বন করুন। এটি সেই বস্তুর একই উদাহরণ দিয়ে অ্যারে পূরণ করবে (কেউ আলাদা উদাহরণ আশা করতে পারে)
অ্যান্ডি হিন

ঠিক আছে, তবে এটি ওপি প্রশ্নটি সমাধান করে, অ্যারেও একই উদাহরণের বস্তুতে ভরাট জেনে তারপর আপনাকে এটি মোকাবেলা করতে হবে, কোনও অপরাধ হবে না।
কার্লোস.ভি

5

আপাতত, শব্দার্থগতভাবে নিকটতম একটি নির্দিষ্ট সংখ্যক উপাদানগুলির সাথে একটি টিউপল হবে।

typealias buffer = (
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode)

তবে এটি (1) ব্যবহার করা খুব অস্বস্তিকর এবং (2) মেমরির বিন্যাস অপরিজ্ঞাত। (কমপক্ষে আমার অজানা)


5

সুইফট 4

আপনি এটি সম্পর্কে কিছুটা রেফারেন্সের বনাম বনাম অ্যারের হিসাবে ভাবতে পারেন।

  • [SKSpriteNode] সত্যিকারের অবজেক্ট অবশ্যই থাকতে হবে
  • [SKSpriteNode?] হয় বস্তুর রেফারেন্স থাকতে পারে, বা nil

উদাহরণ

  1. Default৪ ডিফল্ট দিয়ে একটি অ্যারে তৈরি করা হচ্ছে SKSpriteNode:

    var sprites = [SKSpriteNode](repeatElement(SKSpriteNode(texture: nil),
                                               count: 64))
    
  2. 64 টি খালি স্লট (ওরফে বিকল্প ) দিয়ে একটি অ্যারে তৈরি করা হচ্ছে :

    var optionalSprites = [SKSpriteNode?](repeatElement(nil,
                                          count: 64))
    
  3. বস্তু (ধ্বসে একটি অ্যারের মধ্যে optionals একটি অ্যারের রূপান্তর [SKSpriteNode?]মধ্যে [SKSpriteNode]):

    let flatSprites = optionalSprites.flatMap { $0 }
    

    countফলে flatSpritesবস্তু গণনা উপর নির্ভর করে optionalSprites: খালি optionals উপেক্ষা করা হবে, অর্থাত্ এড়ানো।


flatMapঅবচয় করা হয়েছে, এটি compactMapসম্ভব হলে আপডেট করা উচিত । (আমি এই উত্তরটি সম্পাদনা করতে পারি না)
হালোজেরো

1

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

let count = 64
let sprites = UnsafeMutableBufferPointer<SKSpriteNode>.allocate(capacity: count)

for i in 0..<count {
    sprites[i] = ...
}

for sprite in sprites {
    print(sprite!)
}

sprites.deallocate()

এটি অবশ্য খুব বেশি ব্যবহারকারী বান্ধব নয়। তো, আসুন একটি মোড়ক তৈরি করি!

class ConstantSizeArray<T>: ExpressibleByArrayLiteral {
    
    typealias ArrayLiteralElement = T
    
    private let memory: UnsafeMutableBufferPointer<T>
    
    public var count: Int {
        get {
            return memory.count
        }
    }
    
    private init(_ count: Int) {
        memory = UnsafeMutableBufferPointer.allocate(capacity: count)
    }
    
    public convenience init(count: Int, repeating value: T) {
        self.init(count)
        
        memory.initialize(repeating: value)
    }
    
    public required convenience init(arrayLiteral: ArrayLiteralElement...) {
        self.init(arrayLiteral.count)
        
        memory.initialize(from: arrayLiteral)
    }
    
    deinit {
        memory.deallocate()
    }
    
    public subscript(index: Int) -> T {
        set(value) {
            precondition((0...endIndex).contains(index))
            
            memory[index] = value;
        }
        get {
            precondition((0...endIndex).contains(index))
            
            return memory[index]
        }
    }
}

extension ConstantSizeArray: MutableCollection {
    public var startIndex: Int {
        return 0
    }
    
    public var endIndex: Int {
        return count - 1
    }
    
    func index(after i: Int) -> Int {
        return i + 1;
    }
}

এখন, এটি একটি শ্রেণি, এবং কোনও কাঠামো নয়, সুতরাং এখানে ওভারহেড ব্যয় করা কিছু রেফারেন্স রয়েছে। আপনি এটিকে structপরিবর্তে পরিবর্তন করতে পারেন , তবে যেহেতু সুইফ্ট আপনাকে অনুলিপি আরম্ভের deinitকাঠামোগুলি ব্যবহার করার ক্ষমতা সরবরাহ করে না , আপনার একটি বিলোপ পদ্ধতি ( func release() { memory.deallocate() }) প্রয়োজন হবে এবং কাঠামোর সমস্ত অনুলিপি একই মেমরির উল্লেখ করবে reference

এখন, এই শ্রেণিটি যথেষ্ট যথেষ্ট হতে পারে। এর ব্যবহার সহজ:

let sprites = ConstantSizeArray<SKSpriteNode?>(count: 64, repeating: nil)

for i in 0..<sprites.count {
    sprite[i] = ...
}

for sprite in sprites {
    print(sprite!)
}

আরো প্রোটোকল থেকে অনুরূপ বাস্তবায়ন জন্য, দেখুন এরে ডকুমেন্টেশন (স্ক্রোল সম্পর্ক )।


-3

একটি জিনিস আপনি করতে পারেন তা হ'ল অভিধান তৈরি করা। আপনার 64 টি উপাদানের সন্ধানের জন্য বিবেচনা করে একটু ঝিমঝিম হতে পারে তবে এটি কাজটি হয়ে যায়। আমি নিশ্চিত না যে এটির "পছন্দসই উপায়" এটি করার জন্য তবে এটি আমার পক্ষে স্ট্রাক্টের অ্যারে ব্যবহার করে কাজ করেছিল।

var tasks = [0:[forTasks](),1:[forTasks](),2:[forTasks](),3:[forTasks](),4:[forTasks](),5:[forTasks](),6:[forTasks]()]

4
অ্যারের চেয়ে এটি কীভাবে ভাল? আমার কাছে এটি একটি হ্যাক যা এমনকি সমস্যার সমাধানও করে না: আপনি tasks[65] = fooএই ক্ষেত্রে এবং প্রশ্ন থেকে একটি অ্যারের ক্ষেত্রে উভয় ক্ষেত্রে খুব ভাল করতে পারেন ।
ল্যাক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.