How to extract values from Arrays

I have a problem with extracting values from an array that only has one index, however, it has many values. Example below

array = [(fruit, milk, cheese, cake)]

So how can I extract those variables so that for example if I had a normal array with 4 indices (index)

easyarray = [ceral, chocolate, brownie, fish]

With an easy array, I can call up the values with a simple .map {$0._____}

But how do I do that, or a different function (function referring to being able to extract the values cheese, milk etc).

Much thanks

Accepted Reply

You are confusing a lot of things, because you do not use types properly.


var extract = selected.map {$0.rect} // running other functions. mapping out what we need, rect is my rectangle info 
let finishedextracting = extract.flatMap()  { [$0.0, $0.1, $0.2, $0.3]} 
//The error shows the 0, 1, 2, and 3, in 0.0 etc, dont exist in CGRect


I understand extract is a CGRect or probably an array with a CGRect.

So its internal struct is not a 4-uple (x, y, width, height), but a struct (origin: CGPoint, size: CGSize)

so line 2 does not make work.

But you could write:

var extract = selected.map {$0.rect} // running other functions. mapping out what we need, rect is my rectangle info 
let finishedExtracting = extract.flatMap()  { [$0.origin, $0.size]}

You will get origin and size, as an array of pairs

[(100.0, 40.0), (200.0, 30.0)]


What do you want to get in finishedExtracting ?

- An array with x, y, width, height ?

In such a case, you could replace

var extract = selected.map {$0.rect}

by

var extract = selected.map {$0.rect}[0]     // Get the first element

extract is no more an array but a single CGRect, with origin and size properties.

and replace line 2 by

let (x, y, width, height) = (extract.origin.x, extract.origin.y, extract.size.width, extract.size.height)
let finishedExtracting = [x, y, width, height]


- the origin and size ?

In such a case, replace

var extract = selected.map {$0.rect}

by

var extract = selected.map {$0.rect}[0]     // Get the first element

extract is no more an array but a single CGRect, with origin and size properties.

and replace line 2 by

let (origin, size) = (extract.origin, extract.size)

Here you cannot set directly finishedExtracting

Replies

If you know it is a 4-uple, you can write:


let testArray = [("fruit", "milk", "cheese", "cake")]
let newArray = testArray.flatMap()  { [$0.0, $0.1, $0.2, $0.3]}
print(newArray)


to get the easyArray:

["fruit", "milk", "cheese", "cake"]


Note: I supposed it was Strings as "milk"

The previous works with an array of several tuples:


let testArray = [("fruit", "milk", "cheese", "cake"), ("fruit2", "milk2", "cheese2", "cake2")]
let newArray = testArray.flatMap()  { [$0.0, $0.1, $0.2, $0.3]}
print(newArray)


But that assumes that each t-uple has exactly 4 items.


If you want something generic, which works with t-uples of any and even different size:

Credit : h ttps://gist.github.com/ctreffs/785db636d68a211b25c989644b13f301


func makeArray<tuple, value="">(from tuple: Tuple) -> [Value] {
    let tupleMirror = Mirror(reflecting: tuple)
    assert(tupleMirror.displayStyle == .tuple, "Given argument is no tuple")
    assert(tupleMirror.superclassMirror == nil, "Given tuple argument must not have a superclass (is: \(tupleMirror.superclassMirror!)")

    assert(!tupleMirror.children.isEmpty, "Given tuple argument has no value elements")
    func convert(child: Mirror.Child) -> Value? {
        let valueMirror = Mirror(reflecting: child.value)
        assert(valueMirror.subjectType == Value.self, "Given tuple argument's child type (\(valueMirror.subjectType)) does not reflect expected return value type (\(Value.self))")
        return child.value as? Value
    }

    return tupleMirror.children.compactMap(convert)
}

let testArray2 = [("fruit", "milk", "cheese", "cake"), ("fruit2", "milk2", "cheese2", "cake2", "wine2")] as [Any]   

var resultArray : [String] = []
for tuple in testArray2 {
    let strArray: [String] = makeArray(from: tuple)
    resultArray.insert(contentsOf: strArray, at: resultArray.count)
}
print(resultArray)


Yielding:

["fruit", "milk", "cheese", "cake", "fruit2", "milk2", "cheese2", "cake2", "wine2"]



Note that as [Any] required, because tuple are of different size, hence it is an array of inhomogeneous objects, leading to the error:

Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional

I can call up the values with a simple .map {$0._____}


If you want to apply something like `map` to a tuple, no way.

No `map`, no `for-in`, no subscript ... on tuples like `(fruit, milk, cheese, cake)`.


If you need such operations, DO NOT USE tuples.

You may convert tuples into an Array as shown in Claude31's answer, but NOT USING tuples would be a better way.


Please clarify what you really want to do, do you really need to work with an Array of single tuple?

I have an assignment that says something like this

"Extract the values from the rectangle values that are located in the tuple inside an array below

[(120, 375, 24, 24)] "

It should be simple, but I can't extract it. There are no labels or something

If you write:


let rectArray = [(120, 375, 24, 24)]
let newArray = rectArray.flatMap()  { [$0.0, $0.1, $0.2, $0.3]}

You'll get it.


but you can also simply write:


let (x, y, width, height) = rectArray[0] // That's a single element array

Now, you can use all var as needed


print("x origin is", x)
print("width is", width)

So I'm putting the first one in wit the .flatMap, and it's throwing an error saying that value of type 'CGRECT' has no type '0', and so one for the other ones. any suggestions?

here's the current code with that error

var extract = selected.map {$0.rect} // running other functions. mapping out what we need, rect is my rectangle info
let finishedextracting = extract.flatMap()  { [$0.0, $0.1, $0.2, $0.3]}
//The error shows the 0, 1, 2, and 3, in 0.0 etc, dont exist in CGRect

You are confusing a lot of things, because you do not use types properly.


var extract = selected.map {$0.rect} // running other functions. mapping out what we need, rect is my rectangle info 
let finishedextracting = extract.flatMap()  { [$0.0, $0.1, $0.2, $0.3]} 
//The error shows the 0, 1, 2, and 3, in 0.0 etc, dont exist in CGRect


I understand extract is a CGRect or probably an array with a CGRect.

So its internal struct is not a 4-uple (x, y, width, height), but a struct (origin: CGPoint, size: CGSize)

so line 2 does not make work.

But you could write:

var extract = selected.map {$0.rect} // running other functions. mapping out what we need, rect is my rectangle info 
let finishedExtracting = extract.flatMap()  { [$0.origin, $0.size]}

You will get origin and size, as an array of pairs

[(100.0, 40.0), (200.0, 30.0)]


What do you want to get in finishedExtracting ?

- An array with x, y, width, height ?

In such a case, you could replace

var extract = selected.map {$0.rect}

by

var extract = selected.map {$0.rect}[0]     // Get the first element

extract is no more an array but a single CGRect, with origin and size properties.

and replace line 2 by

let (x, y, width, height) = (extract.origin.x, extract.origin.y, extract.size.width, extract.size.height)
let finishedExtracting = [x, y, width, height]


- the origin and size ?

In such a case, replace

var extract = selected.map {$0.rect}

by

var extract = selected.map {$0.rect}[0]     // Get the first element

extract is no more an array but a single CGRect, with origin and size properties.

and replace line 2 by

let (origin, size) = (extract.origin, extract.size)

Here you cannot set directly finishedExtracting

Did you solve your issue ?


If so, don't forget to close the thread.

Yes, thank you, the wifi must have disconnected or something because I pressed it, or I might have forgotten... But thank you