DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • A Developer’s Guide to Multithreading and Swift Concurrency
  • Why You Might Need To Know Algorithms as a Mobile Developer: Emoji Example
  • Make @Observable Wrapper for Better State Control in Swift
  • Reversing an Array: An Exploration of Array Manipulation

Trending

  • A Developer's Guide to Mastering Agentic AI: From Theory to Practice
  • Medallion Architecture: Why You Need It and How To Implement It With ClickHouse
  • How to Convert XLS to XLSX in Java
  • AI-Driven Test Automation Techniques for Multimodal Systems
  1. DZone
  2. Data Engineering
  3. Data
  4. ArraySlice in Swift

ArraySlice in Swift

See how the ArraySlice object allows us to perform array operations like append and map on a slice when developing with Swift.

By 
Marco Santarossa user avatar
Marco Santarossa
·
Oct. 11, 17 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
18.2K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

Apple describes ArraySlice as “Views onto Arrays.” It means that an ArraySlice is an object which represents a subsequence of its array. It’s very powerful and allows us to perform the same array operations on a slice like append, map and so on.

In this article, we will see how to create it and some internal behaviors to avoid troubles.

Happy reading!

How to Create An ArraySlice

Before using an ArraySlice, we must understand how to create it. Swift provides several ways to get a slice from a given array:

Drop

Array provides some methods to create a subsequence, removing some elements. These methods are dropFirst, dropLast and drop:

let array = [5, 2, 10, 1, 0, 100, 46, 99]

// Drops first
array.dropFirst() // ArraySlice<Int>[2, 10, 1, 0, 100, 46, 99]

// Drops first three elements
array.dropFirst(3) // ArraySlice<Int>[1, 0, 100, 46, 99]

/ Drops last
array.dropLast() // ArraySlice<Int>[5, 2, 10, 1, 0, 100, 46]

// Drops last three elements
array.dropLast(3) // ArraySlice<Int>[5, 2, 10, 1, 0]

// Drops all the elements less than 15
array.drop { $0 < 15 } // ArraySlice<Int>[100, 46, 99]

Prefix

If we want to create a subsequence with the first elements of a given array, we can use the method prefix:

let array = [5, 2, 10, 1, 0, 100, 46, 99]

// First 4 elements
array.prefix(4) // ArraySlice<Int>[5, 2, 10, 1]

// First elements until the index 4, excluding the element at index 4
array.prefix(upTo: 4) // ArraySlice<Int>[5, 2, 10, 1]

// First elements until the index 4, including the element at index 4
array.prefix(through: 4) // ArraySlice<Int>[5, 2, 10, 1, 0]

// First elements until the condition fails (in this case, the elements must be less than 10)
array.prefix { $0 < 10 } // ArraySlice<Int>[5, 2]

Suffix

suffix has the opposite behavior of prefix. It returns the last elements of the array:

let array = [5, 2, 10, 1, 0, 100, 46, 99]

// Last 3 elements
array.suffix(3) // ArraySlice<Int>[100, 46, 99]

// Last elements from the index 5, including the element at index 5
array.suffix(from: 5) // ArraySlice<Int>[100, 46, 99]

Range

We can also create an ArraySlice using a range of indices:

let array = [5, 2, 10, 1, 0, 100, 46, 99]

// From index 3 to index 5
array[3...5] // ArraySlice<Int>[1, 0, 100]

// From index 3 to index less than 5
array[3..<5] // ArraySlice<Int>[1, 0]

With Swift 4, we can omit the startIndex if we want to use the index 0 and the endIndex if we want to use the last index of the array:

let array = [5, 2, 10, 1, 0, 100, 46, 99]

// From index 0 to index 2
array[...2] // ArraySlice<Int> [5, 2, 10]

// From index 0 to index less than 2
array[..<2] // ArraySlice<Int> [5, 2]

// From index 6 to index 7
array[6...] // ArraySlice<Int> [46, 99]

// From index 0 to index 7
array[...] // ArraySlice<Int> [5, 2, 10, 1, 0, 100, 46, 99]

Convert ArraySlice to Array

Let’s suppose that we want to remove the last five elements from an array. We can use the method dropLast(5) and assign the result to the array:

var array = [5, 2, 10, 1, 0, 100, 46, 99]

let slice = array.dropLast(5)
array = slice // Cannot assign value of type 'ArraySlice<Int>' to type '[Int]'

Unfortunately, Swift doesn’t allow to assign an ArraySlice object to an Array. For this reason, in example above, we have a compile error Cannot assign value of type 'ArraySlice<Int>' to type '[Int]'. We need a way to convert the ArraySlice object to Array. Fortunately, Swift allows us to cast the slice variable using the syntax Array(<slice_variable>). We can use this cast to fix the example above like this:

var array = [5, 2, 10, 1, 0, 100, 46, 99]

let slice = array.dropLast(5)
array = Array(slice) // [5, 2, 10]

Relation Between ArraySlice and Its Array

Strong Reference

ArraySlice holds a strong reference of its array. It means that we should pay attention to how we use the slice to avoid troubles with the memory. Apple also added a warning about it in the documentation:

"Long-term storage of ArraySlice instances is discouraged. A slice holds a reference to the entire storage of a larger array, not just to the portion it presents, even after the original array’s lifetime ends. Long-term storage of a slice may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory and object leakage." -Source.

We can test this behavior with the following example:

final class Element {
    deinit {
        print("Element deinit is called")
    }
}

final class ArrayHandler {
    let array = [Element(), Element()]
}

final class Main {
    var slice: ArraySlice<Element>

    init() {
        let arrayHandler = ArrayHandler()
        slice = arrayHandler.array.dropLast() // `slice` holds a strong reference of `arrayHandler.array`
    }
}

let main = Main()

If we run this example, we notice that the property slice holds a strong reference of the array elements. Even though arrayHandler is destroyed at the end of the init scope, the deinit method of Element is not called.

Consequences of ArraySlice and Array changes

Let’s suppose that we have an Array and an its ArraySlice. If we change the elements of the Array, the ArraySlice won’t be affected and will continue storing the original elements:

var array = [10, 46, 99]
let slice = array.dropLast() // ArraySlice<Int> [10, 46]
array.append(333) // [10, 46, 99, 333]

// `slice` is not affected and continues storing the original elements
print(slice) // ArraySlice<Int> [10, 46]

Vice versa, if we change the elements of an ArraySlice, its Array won’t be affected:

let array = [10, 46, 99]
var slice = array.dropLast() // ArraySlice<Int> [10, 46]
slice.append(333) // ArraySlice<Int> [10, 46, 333]

// `array` is not affected and continues storing the original elements
print(array) // [10, 46, 99]

Slice Indices

ArraySlice maintains the same indices of its array. It means that the element at index 3 of an ArraySlice is the same element at the index 3 of its original array.

Let’s consider an ArraySlice with a range 2...4. If we try reading the element at index 0 of the slice, we would have a runtime error:

let array = [10, 46, 99, 00, 6]
var slice = array[2...4] // ArraySlice<Int> [99, 0, 6]

slice[0] // fatal error: Index out of bounds

It happens because the slice doesn’t contain the element at index 0 of the array but only the elements at index 2, 3 and 4.

If we want to get the first and last index of a slice in a safe way, we should use startIndex and endIndex:

let array = [10, 46, 99, 00, 6]
var slice = array[2...4] // ArraySlice<Int> [99, 0, 6]

slice[slice.startIndex] // 99
slice[slice.endIndex - 1] // 6

endIndex returns the position one greater than the last valid index. For this reason, we must use endIndex - 1 in the example above to avoid an Index out of bounds error.

Conclusion

In addition to ArraySlice, Swift provides also a base object Slice. It allows us to get a subsequence of other collection objects like Dictionary, Set and any kind of custom collection.

Swift (programming language) Data structure Element

Published at DZone with permission of Marco Santarossa, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • A Developer’s Guide to Multithreading and Swift Concurrency
  • Why You Might Need To Know Algorithms as a Mobile Developer: Emoji Example
  • Make @Observable Wrapper for Better State Control in Swift
  • Reversing an Array: An Exploration of Array Manipulation

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: