อาร์เรย์ใหม่จาก Index Range Swift


123

ฉันจะทำเรื่องแบบนี้ได้อย่างไร? นำ n องค์ประกอบแรกจากอาร์เรย์:

newNumbers = numbers[0..n]

ขณะนี้ได้รับข้อผิดพลาดต่อไปนี้:

error: could not find an overload for 'subscript' that accepts the supplied arguments

แก้ไข:

นี่คือฟังก์ชันที่ฉันกำลังทำงานอยู่

func aFunction(numbers: Array<Int>, position: Int) -> Array<Int> {
    var newNumbers = numbers[0...position]
    return newNumbers
}

คำตอบ:


182

สิ่งนี้ใช้ได้กับฉัน:

var test = [1, 2, 3]
var n = 2
var test2 = test[0..<n]

ปัญหาของคุณอาจมาจากวิธีที่คุณประกาศว่าอาร์เรย์ของคุณจะเริ่มต้นด้วยวิธีใด

แก้ไข:

ในการแก้ไขฟังก์ชันของคุณคุณต้องส่งSliceไปยังอาร์เรย์:

func aFunction(numbers: Array<Int>, position: Int) -> Array<Int> {
    var newNumbers = Array(numbers[0..<position])
    return newNumbers
}

// test
aFunction([1, 2, 3], 2) // returns [1, 2]

ฉันได้เพิ่มบริบทให้กับคำถามของฉันอีกเล็กน้อยฉันกำลังทำงานในฟังก์ชัน สิ่งนี้ทำงานได้อย่างอิสระ แต่ไม่อยู่ในฟังก์ชัน
Charlie Egan

1
น่ารัก! ไชโย - ได้ผล ฉันจะยอมรับคำตอบเมื่อมันให้ฉัน
Charlie Egan

23
Pedantic point แต่นี่ไม่ได้เป็นการส่งต่อSliceไปยัง an Arrayแต่เป็นการสร้างอาร์เรย์ใหม่จากชิ้นส่วน นักแสดงจะใช้ตัวasดำเนินการnumbers as Arrayซึ่งจะทำให้เกิดข้อผิดพลาด
jb

ภาษามีการเปลี่ยนแปลงโดยใช้จุดไข่ปลาสามจุดและไม่ใช่สองdeveloper.apple.com/library/ios/documentation/General/Reference/…
Daniel Galasko

2
จุดสองจุด..เปลี่ยนเป็น..<; จุดสามจุด (จุดไข่ปลา) ยังคงเหมือนเดิม ขอบคุณสำหรับการแจ้งเตือนแม้ว่า; ฉันอัปเดตคำตอบแล้ว
Cezary Wojcik

100

# 1 การใช้ตัวArrayห้อยกับช่วง

ด้วย Swift 5 เมื่อคุณเขียน ...

let newNumbers = numbers[0...position]

... newNumbersไม่ได้เป็นชนิดแต่เป็นประเภทArray<Int> ArraySlice<Int>นั่นเป็นเพราะArray's subscript(_:​)ส่งกลับArraySlice<Element>ว่าตามที่แอปเปิ้ลนำเสนอมุมมองที่เข้าสู่การจัดเก็บของบางส่วนอาร์เรย์ขนาดใหญ่

นอกจากนี้ Swift ยังมีArrayinitializer ที่เรียกinit(_:​)ว่าช่วยให้เราสร้างอาร์เรย์ใหม่จากsequence(รวมถึงArraySlice)

ดังนั้นคุณสามารถใช้subscript(_:​)ด้วยinit(_:​)เพื่อให้ได้รับอาร์เรย์ใหม่จากครั้งแรกnองค์ประกอบของอาร์เรย์:

let array = Array(10...14) // [10, 11, 12, 13, 14]
let arraySlice = array[0..<3] // using Range
//let arraySlice = array[0...2] // using ClosedRange also works
//let arraySlice = array[..<3] // using PartialRangeUpTo also works
//let arraySlice = array[...2] // using PartialRangeThrough also works
let newArray = Array(arraySlice)
print(newArray) // prints [10, 11, 12]

# 2 ใช้Array's prefix(_:)วิธี

Swift มีprefix(_:)วิธีการสำหรับประเภทที่สอดคล้องกับCollectionโปรโตคอล (รวมถึงArray) prefix(_:)มีคำประกาศดังต่อไปนี้:

func prefix(_ maxLength: Int) -> ArraySlice<Element>

ส่งคืนค่าตามมาโดยมีความยาวสูงสุด maxLength ที่มีองค์ประกอบเริ่มต้น

Apple ยังระบุ:

หากความยาวสูงสุดเกินจำนวนองค์ประกอบในคอลเล็กชันผลลัพธ์จะมีองค์ประกอบทั้งหมดในคอลเล็กชัน

ดังนั้นเพื่อเป็นทางเลือกอื่นจากตัวอย่างก่อนหน้านี้คุณสามารถใช้โค้ดต่อไปนี้เพื่อสร้างอาร์เรย์ใหม่จากองค์ประกอบแรกของอาร์เรย์อื่น:

let array = Array(10...14) // [10, 11, 12, 13, 14]
let arraySlice = array.prefix(3)
let newArray = Array(arraySlice)
print(newArray) // prints [10, 11, 12]

7
func subArray<T>(array: [T], range: NSRange) -> [T] {
  if range.location > array.count {
    return []
  }
  return Array(array[range.location..<min(range.length, array.count)])
}

โปรดเพิ่มคำอธิบายในคำตอบด้วย
Naman

คำตอบที่ดีมาก สิ่งที่ทำโดยพื้นฐานคือมันร่าย ArraySlice <T> ไปยัง Array โดยส่วนตัวฉันจะไม่รวมคำยืนยันไว้มากนัก ตามปกติแล้วฉันต้องการให้ slice ล้มเหลวหากฉันระบุช่วงเท็จเป็นต้น
eonist

0

อีกหนึ่งตัวแปรที่ใช้extensionและชื่ออาร์กิวเมนต์range

ส่วนขยายนี้ใช้RangeและClosedRange

extension Array {

    subscript (range r: Range<Int>) -> Array {
        return Array(self[r])
    }


    subscript (range r: ClosedRange<Int>) -> Array {
        return Array(self[r])
    }
}

แบบทดสอบ:

func testArraySubscriptRange() {
    //given
    let arr = ["1", "2", "3"]

    //when
    let result = arr[range: 1..<arr.count] as Array

    //then
    XCTAssertEqual(["2", "3"], result)
}

func testArraySubscriptClosedRange() {
    //given
    let arr = ["1", "2", "3"]

    //when
    let result = arr[range: 1...arr.count - 1] as Array

    //then
    XCTAssertEqual(["2", "3"], result)
}

0

วิธีการทำงานของอาร์เรย์:

   array.enumerated().filter { $0.offset < limit }.map { $0.element }

ตั้งแต่:

 array.enumerated().filter { $0.offset >= minLimit && $0.offset < maxLimit }.map { $0.element }

ข้อดีของวิธีนี้คือการนำไปใช้งานนั้นปลอดภัย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.