মান দ্বারা বস্তু সরানোর জন্য অ্যারের এক্সটেনশান


140
extension Array {
    func removeObject<T where T : Equatable>(object: T) {
        var index = find(self, object)
        self.removeAtIndex(index)
    }
}

তবে, আমি একটি ত্রুটি পেয়েছি var index = find(self, object)

'টি' 'টি' তে রূপান্তরিত নয়

আমি এই পদ্ধতির স্বাক্ষর দিয়েও চেষ্টা করেছি: func removeObject(object: AnyObject)তবে, আমি একই ত্রুটি পেয়েছি:

'যেকোনওজেক্ট' 'টি' তে রূপান্তরিত নয়

এটি করার উপযুক্ত উপায় কী?


T whereআপনার পদ্ধতি ঘোষণা থেকে এটিকে অপসারণ করার চেষ্টা করুন । তাই ঠিক func removeObject<T: Equatable>। এই প্রশ্নের সংশ্লিষ্ট হল: stackoverflow.com/questions/24091046/...
ahruss

উত্তর:


165

সুইফট 2 হিসাবে , এটি একটি প্রোটোকল এক্সটেনশন পদ্ধতি দ্বারা অর্জন করা যেতে পারে । removeObject()সমস্ত ধরণের RangeReplaceableCollectionType(বিশেষত উপর Array) মেনে চলার পদ্ধতি হিসাবে সংজ্ঞায়িত করা হয় যদি সংগ্রহের উপাদানগুলি হয় Equatable:

extension RangeReplaceableCollectionType where Generator.Element : Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func removeObject(object : Generator.Element) {
        if let index = self.indexOf(object) {
            self.removeAtIndex(index)
        }
    }
}

উদাহরণ:

var ar = [1, 2, 3, 2]
ar.removeObject(2)
print(ar) // [1, 3, 2]

জন্য আপডেট সুইফট 2 / Xcode 7 বিটা 2: হিসাবে এয়ারস্পীড বেগ মন্তব্য খেয়াল, এটি এখন আসলে সম্ভব একটি জেনেরিক যে ধরনের টেমপ্লেট উপর আরো নিয়ন্ত্রণমূলক উপর একটি পদ্ধতি লিখতে, তাই পদ্ধতি এখন আসলে একটি এক্সটেনশন হিসাবে সংজ্ঞায়িত করা যেতে পারে এর Array:

extension Array where Element : Equatable {

    // ... same method as above ...
}

প্রোটোকল এক্সটেনশনের এখনও আরও বড় ধরণের সেটগুলির ক্ষেত্রে প্রযোজ্য হওয়ার সুবিধা রয়েছে।

সুইফট 3 এর জন্য আপডেট :

extension Array where Element: Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func remove(object: Element) {
        if let index = index(of: object) {
            remove(at: index)
        }
    }
}

1
নিখুঁত, আপনি সুইফট (2) ভালবাসেন। সময়ের সাথে কীভাবে আরও জিনিস সম্ভব হয় এবং জিনিসগুলি সরলীকরণ হয় তা আমি সত্যিই পছন্দ করি
Kametrixom

1
ভাল কথা, বিভিন্ন দিক থেকে উত্তরটি এখনও প্রযুক্তিগতভাবে সঠিক, কেবল আর মূio় নয়, আরও খারাপ - মানুষ আসবে, উত্তরটি পড়বে, মনে করি একটি মুক্ত ফাংশনই এটি সমাধানের সঠিক উপায় কারণ এটি একটি উচ্চ রেটযুক্ত উত্তর । বেশ কুৎসিত দৃশ্য। মেটাতে পোস্ট করবে।
আর্স্পিড বেদটি

1
@ আয়ারস্পিডভেলসিটি: বাহ, আমি তা মিস করেছি। এটি কি রিলিজ নোটগুলিতে আচ্ছাদিত?
মার্টিন আর

1
আপনি যদি ওবিজেসি-র মতো একই কার্যকারিতাটি চান (যেমন কেবলমাত্র 1 ম এর পরিবর্তে সমস্ত মিলে যাওয়া বস্তুগুলি সরিয়ে দেয়), আপনি "যদি" যখন "তে" পরিবর্তন করতে পারেন
পাওয়ারআল্ড

2
সুইফট 3 সংস্করণ দুর্দান্ত, তবে আমি সুইফট এপিআই ডিজাইনের নির্দেশিকাগুলিremove(object: Element) মেনে চলার জন্য এবং ভার্বোসটি এড়াতে এই ঘোষণার নামটির সামান্য পরিবর্তন করব । আমি এটি সম্পাদন করে একটি সম্পাদনা জমা দিয়েছি।
সুইফটকোড

66

আপনি জেনেরিক ধরণে এমন কোনও পদ্ধতি লিখতে পারবেন না যা টেম্পলেটটিতে আরও সীমাবদ্ধ।

উল্লেখ্য : সুইফট 2.0 হিসাবে, আপনি এখন পদ্ধতি লিখতে পারেন হয় টেমপ্লেট উপর আরো নিয়ন্ত্রণমূলক। আপনি যদি আপনার কোডটি ২.০ এ আপগ্রেড করে থাকেন তবে এক্সটেনশনগুলি ব্যবহার করে এটি প্রয়োগ করতে নতুন বিকল্পগুলির জন্য আরও উত্তর নীচে দেখুন।

আপনি 'T' is not convertible to 'T'যে ত্রুটিটি পেয়েছেন তা হ'ল আপনি আসলে আপনার পদ্ধতিতে একটি নতুন টি সংজ্ঞায়িত করছেন যা মূল টির সাথে মোটেই সম্পর্কিত নয় you আপনি যদি আপনার পদ্ধতিতে টি ব্যবহার করতে চান তবে আপনি আপনার পদ্ধতিতে এটি নির্দিষ্ট না করেই এটি করতে পারেন।

আপনি দ্বিতীয় ত্রুটিটি পাওয়ার কারণটি 'AnyObject' is not convertible to 'T'হ'ল টি এর জন্য সমস্ত সম্ভাব্য মানগুলি সমস্ত শ্রেণি নয়। কোনও উদাহরণকে যেকোনওজেক্টে রূপান্তরিত করার জন্য, এটি অবশ্যই একটি শ্রেণি হতে হবে (এটি কোনও স্ট্রাক্ট, এনাম ইত্যাদি হতে পারে না)।

আপনার সেরা বাজি হ'ল এটিকে একটি ফাংশন তৈরি করা যা অ্যারেটিকে আর্গুমেন্ট হিসাবে গ্রহণ করে:

func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) {
}

অথবা আসল অ্যারেটি পরিবর্তনের পরিবর্তে, আপনি অনুলিপি ফিরিয়ে আপনার পদ্ধতিটি আরও থ্রেডকে নিরাপদ এবং পুনরায় ব্যবহারযোগ্য করতে পারেন:

func arrayRemovingObject<T : Equatable>(object: T, fromArray array: [T]) -> [T] {
}

বিকল্প হিসাবে আমি প্রস্তাব দিচ্ছি না, অ্যারেতে সঞ্চিত ধরণটি পদ্ধতি টেমপ্লেটে রূপান্তরিত না করা হলে আপনি চুপচাপ আপনার পদ্ধতিটি ব্যর্থ করতে পারেন (এটি সমানযোগ্য)। (স্পষ্টতার জন্য, আমি পদ্ধতির টেমপ্লেটের জন্য টি এর পরিবর্তে ইউ ব্যবহার করছি):

extension Array {
    mutating func removeObject<U: Equatable>(object: U) {
        var index: Int?
        for (idx, objectToCompare) in enumerate(self) {
            if let to = objectToCompare as? U {
                if object == to {
                    index = idx
                }
            }
        }

        if(index != nil) {
            self.removeAtIndex(index!)
        }
    }
}

var list = [1,2,3]
list.removeObject(2) // Successfully removes 2 because types matched
list.removeObject("3") // fails silently to remove anything because the types don't match
list // [1, 3]

সম্পাদনা নীরব ব্যর্থতা কাটিয়ে উঠতে আপনি সাফল্যটিকে উল হিসাবে ফিরিয়ে দিতে পারেন:

extension Array {
  mutating func removeObject<U: Equatable>(object: U) -> Bool {
    for (idx, objectToCompare) in self.enumerate() {  //in old swift use enumerate(self) 
      if let to = objectToCompare as? U {
        if object == to {
          self.removeAtIndex(idx)
          return true
        }
      }
    }
    return false
  }
}
var list = [1,2,3,2]
list.removeObject(2)
list
list.removeObject(2)
list

আমার উত্তরটি এখানে দেখুন: stackoverflow.com/a/24939242/458960 আমি কেন এইভাবে এটি করতে সক্ষম এবং findপদ্ধতিটি ব্যবহার না করে ?
স্নোম্যান 16

আপনার পদ্ধতি রানটাইম ক্রাশগুলির জন্য সংবেদনশীল। আমার ফাংশন দিয়ে, সংকলকটি এটিকে আদৌ ঘটতে বাধা দেবে।
ড্র্যাগ করুন

1
@ ইসুুরু এই পদ্ধতিটি এমন কোনও বস্তুর সাথে কাজ করে যা Equatableপ্রোটোকল প্রয়োগ করে । ইউআইভিউ তাই হ্যাঁ এটি ইউআইভিউয়ের সাথে কাজ করবে
ড্রুয়েগ করুন

4
বাহ, একটি উপাদান সরানোর জন্য লুপের জন্য লিখতে, 90 এর দশকে ফিরে!
জোড়ায়ার

5
সর্বশেষতম দ্রুতগতিতে। enumerate(self)ঠিক করতে হবেself.enumerate()
টমসওয়ায়ার

28

সংক্ষেপে এবং সংক্ষিপ্তভাবে:

func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) 
{
    var index = find(array, object)
    array.removeAtIndex(index!)
}

2
এটি দুর্দান্ত। অবশ্যই এটি ছাড়াও করা যেতে পারে inoutinoutঅক্ষত থাকা সত্ত্বেও , কেউ ব্যবহার করতে পারে array = array.filter() { $0 != object }, আমি মনে করি।
ড্যান রোজনস্টার্ক

11
জোর করে মোড়কানো সূচি ব্যবহার করার বিষয়ে সচেতন হোন, যা শূন্য হতে পারে। "If ind = index {array.removeAtIndex (ind)}"
হটজার্ড

17

উপরের সমস্তটি পড়ার পরে, আমার মনে সর্বোত্তম উত্তরটি হ'ল:

func arrayRemovingObject<U: Equatable>(object: U, # fromArray:[U]) -> [U] {
  return fromArray.filter { return $0 != object }
}

নমুনা:

var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = arrayRemovingObject("Cat", fromArray:myArray )

সুইফট 2 (এক্সকোড 7 বি 4) অ্যারে এক্সটেনশন:

extension Array where Element: Equatable {  
  func arrayRemovingObject(object: Element) -> [Element] {  
    return filter { $0 != object }  
  }  
}  

নমুনা:

var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = myArray.arrayRemovingObject("Cat" )

সুইফট ৩.১ আপডেট

এখনই ফিরে এসেছিল যে সুইফট ৩.১ শেষ হয়েছে। নীচে একটি এক্সটেনশন দেওয়া হয়েছে যা পরিপূর্ণ, দ্রুত, পরিবর্তন এবং রূপগুলি তৈরি করে।

extension Array where Element:Equatable {
    public mutating func remove(_ item:Element ) {
        var index = 0
        while index < self.count {
            if self[index] == item {
                self.remove(at: index)
            } else {
                index += 1
            }
        }
    }

    public func array( removing item:Element ) -> [Element] {
        var result = self
        result.remove( item )
        return result
    }
}

নমুনা:

// Mutation...
      var array1 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"]
      array1.remove("Cat")
      print(array1) //  ["Dog", "Turtle", "Socks"]

// Creation...
      let array2 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"]
      let array3 = array2.array(removing:"Cat")
      print(array3) // ["Dog", "Turtle", "Fish"]

এই অ্যারের সম্পূর্ণ নতুন উদাহরণ ফিরে আসে না?
পিএক্সগ্রাফিক্স

হ্যাঁ. এটি আরও কার্যকরী শৈলী। YMMV।
ডিসেম্বর

আমি যদি filterফাংশনটি ইতিমধ্যে আপনার জন্য সেই কার্যকারিতাটি পরিচালনা করে তবে এই ক্ষেত্রে বাদে আমি কার্যকরী স্টাইলিংয়ের সাথে একমত হতে চাই । এটি কার্যকারিতা সদৃশ বলে মনে হচ্ছে। তবে তবুও একটি ভাল উত্তর:]
pxpographicics

13

প্রোটোকল এক্সটেনশনগুলির সাহায্যে আপনি এটি করতে পারেন,

extension Array where Element: Equatable {
    mutating func remove(object: Element) {
        if let index = indexOf({ $0 == object }) {
            removeAtIndex(index)
        }
    }
}

ক্লাসগুলির জন্য একই কার্যকারিতা,

সুইফট 2

extension Array where Element: AnyObject {
    mutating func remove(object: Element) {
        if let index = indexOf({ $0 === object }) {
            removeAtIndex(index)
        }
    }
}

সুইফট 3

extension Array where Element: AnyObject {
    mutating func remove(object: Element) {
        if let index = index(where: { $0 === object }) {
             remove(at: index)
        }
    }
}

তবে কোনও শ্রেণি যদি সমতুল্য প্রয়োগ করে তবে এটি দ্ব্যর্থক হয়ে যায় এবং সংকলক একটি ত্রুটি দেয়।


1
আমি 1Binary operator '===' cannot be applied to two elements of type '_' and 'Element'
জুতো

6

সুইট ২.০ এ প্রোটোকল এক্সটেনশন ব্যবহার করে

extension _ArrayType where Generator.Element : Equatable{
    mutating func removeObject(object : Self.Generator.Element) {
        while let index = self.indexOf(object){
            self.removeAtIndex(index)
        }
    }
}

4

ফিল্টারিং ব্যবহার সম্পর্কে কি? নীচেরগুলি [AnyObject] এর সাথেও বেশ ভাল কাজ করে।

import Foundation
extension Array {
    mutating func removeObject<T where T : Equatable>(obj: T) {
        self = self.filter({$0 as? T != obj})
    }

}

2

অনিরাপদ ব্যবহার সম্ভব না করে অ্যারে থেকে কোনও আইটেম সরানোর আর একটি সম্ভাবনা রয়েছে, কারণ অপসারণের জন্য জেনেরিক ধরণের জিনিসটি অ্যারের ধরণের মতো হতে পারে না। Usingচ্ছিক ব্যবহারগুলিও খুব ধীর হওয়ায় যাওয়ার সঠিক উপায় নয়। উদাহরণস্বরূপ কোনও অ্যারে বাছাই করার সময় আপনি ইতিমধ্যে এটি ব্যবহার করার মতো ক্লোজারটি ব্যবহার করতে পারেন।

//removes the first item that is equal to the specified element
mutating func removeFirst(element: Element, equality: (Element, Element) -> Bool) -> Bool {
    for (index, item) in enumerate(self) {
        if equality(item, element) {
            self.removeAtIndex(index)
            return true
        }
    }
    return false
}

আপনি যখন Arrayএই ফাংশনটি দিয়ে ক্লাসটি প্রসারিত করবেন আপনি নিম্নলিখিতগুলি দ্বারা উপাদানগুলি সরিয়ে ফেলতে পারবেন:

var array = ["Apple", "Banana", "Strawberry"]
array.removeFirst("Banana") { $0 == $1 } //Banana is now removed

তবে আপনি এমনকি কোনও উপাদানটিকে কেবল একই মেমরি ঠিকানা থাকলে (কেবলমাত্র AnyObjectপ্রোটোকলের সাথে সঙ্গতিপূর্ণ ক্লাসগুলির জন্য ) সরাতে পারেন :

let date1 = NSDate()
let date2 = NSDate()
var array = [date1, date2]
array.removeFirst(NSDate()) { $0 === $1 } //won't do anything
array.removeFirst(date1) { $0 === $1 } //array now contains only 'date2'

ভাল জিনিসটি হল, আপনি তুলনা করার জন্য প্যারামিটার নির্দিষ্ট করতে পারেন। উদাহরণস্বরূপ যখন আপনার কাছে অ্যারে থাকে, আপনি সমতা বন্ধ হিসাবে নির্দিষ্ট করতে পারেন{ $0.count == $1.count } এবং সরানোর জন্য একই আকারের প্রথম অ্যারেটি অ্যারে থেকে সরানো হয়।

এমনকি ফাংশনটি যেমন রেখে ফাংশন কলটি সংক্ষিপ্ত করতে পারে mutating func removeFirst(equality: (Element) -> Bool) -> Bool, তারপরে if-মূল্যায়নটি প্রতিস্থাপন করুন equality(item)এবং array.removeFirst({ $0 == "Banana" })উদাহরণস্বরূপ ফাংশনটি কল করতে পারেন ।


যেহেতু ==একটি ফাংশন তাই আপনি যেকোন প্রকারের প্রয়োগ ==(যেমন স্ট্রিং, ইন্ট ইত্যাদি) এর জন্য এটি এটিকে ডাকতে পারেন :array.removeFirst("Banana", equality:==)
অ্যাভিয়েল গ্রস

@ অ্যাভিয়েলগ্রস এটি সুইফট 2-এ নতুন বলে আমি মনে করি - আপনি যদি চান তবে উত্তরটি সম্পাদন করতে
নির্দ্বিধায়

2

প্রসারিত করার দরকার নেই:

var ra = [7, 2, 5, 5, 4, 5, 3, 4, 2]

print(ra)                           // [7, 2, 5, 5, 4, 5, 3, 4, 2]

ra.removeAll(where: { $0 == 5 })

print(ra)                           // [7, 2, 4, 3, 4, 2]

if let i = ra.firstIndex(of: 4) {
    ra.remove(at: i)
}

print(ra)                           // [7, 2, 3, 4, 2]

if let j = ra.lastIndex(of: 2) {
    ra.remove(at: j)
}

print(ra)                           // [7, 2, 3, 4]

1

indexOfএকটি forবা এর পরিবর্তে ব্যবহার করা enumerate:

extension Array where Element: Equatable {

   mutating func removeElement(element: Element) -> Element? {
      if let index = indexOf(element) {
         return removeAtIndex(index)
      }
      return nil
   }

   mutating func removeAllOccurrencesOfElement(element: Element) -> Int {
       var occurrences = 0
       while true {
          if let index = indexOf(element) {
             removeAtIndex(index)
             occurrences++
          } else {
             return occurrences
          }
       }
   }   
}

1

প্রশ্নটা হয়তো বুঝতে পারিনি।

কেন এই কাজ করবে না?

import Foundation
extension Array where Element: Equatable {
    mutating func removeObject(object: Element) {
        if let index = self.firstIndex(of: object) {
            self.remove(at: index)
        }
    }
}

var testArray = [1,2,3,4,5,6,7,8,9,0]
testArray.removeObject(object: 6)
let newArray = testArray

var testArray2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
testArray2.removeObject(object: "6")
let newArray2 = testArray2

0

আমি অবশেষে নিম্নলিখিত কোড দিয়ে শেষ করেছি।

extension Array where Element: Equatable {

    mutating func remove<Element: Equatable>(item: Element) -> Array {
        self = self.filter { $0 as? Element != item }
        return self
    }

}

0

আমি সূচকের প্রতিনিধিত্ব করতে লুপের বাইরে একটি গণনা প্রয়োগ করে এবং এর সাথে সামঞ্জস্যপূর্ণ না হয়ে [String:AnyObject]অ্যারে থেকে একটি মুছে ফেলতে সক্ষম হয়েছি ।[[String:AnyObject]].find.filter[String:AnyObject]

let additionValue = productHarvestChoices[trueIndex]["name"] as! String
var count = 0
for productHarvestChoice in productHarvestChoices {
  if productHarvestChoice["name"] as! String == additionValue {
    productHarvestChoices.removeAtIndex(count)
  }
  count = count + 1
}

-1

সুইফট 2 এ বাস্তবায়ন:

extension Array {
  mutating func removeObject<T: Equatable>(object: T) -> Bool {
    var index: Int?
    for (idx, objectToCompare) in self.enumerate() {
      if let toCompare = objectToCompare as? T {
        if toCompare == object {
          index = idx
          break
        }
      }
    }
    if(index != nil) {
      self.removeAtIndex(index!)
      return true
    } else {
      return false
    }
  }
}

-4

আমি এটি দিয়ে কাজ করতে সক্ষম হয়েছি:

extension Array {
    mutating func removeObject<T: Equatable>(object: T) {
        var index: Int?
        for (idx, objectToCompare) in enumerate(self) {
            let to = objectToCompare as T
            if object == to {
                index = idx
            }
        }

        if(index) {
            self.removeAtIndex(index!)
        }
    }
}

তুলনাটি if(index)অবৈধ
জুন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.