Reputation: 743
help me find an array in the array. In this implementation, I return the entire array.
[(name: "Bell 2", arr: [arrSub(sub_txt: "Test 2, 1"),arrSub(sub_txt: "Test 2, 2")])]
I need to return:
[(name: "Bell 2", arr: [arrSub(sub_txt: "Test 2, 2")])]
// Playground
import UIKit
struct arrSub {
let sub_txt: String
}
struct test {
let name: String
let arr: [arrSub]
init(name: String, arr: [arrSub]) {
self.name = name
self.arr = arr
}
}
var testArr = [test]()
testArr.append(test(name: "Line 1", arr: [arrSub(sub_txt: "Line 1, 1"), arrSub(sub_txt: "Line 1, 2")]))
testArr.append(test(name: "Bell 2", arr: [arrSub(sub_txt: "Bell 2, 1"), arrSub(sub_txt: "Bell 2, 2")]))
testArr.append(test(name: "Bell 2", arr: [arrSub(sub_txt: "Test 2, 1"), arrSub(sub_txt: "Test 2, 2")]))
let new = testArr.filter({
$0.arr.contains(where: { $0.sub_txt.contains("Test 2, 2") } )
})
print(new)
Upvotes: 1
Views: 98
Reputation: 6067
You can use reduce
also
let news = testArr.reduce([test]()) { (result, testObj) -> [test] in
let internalArray = testObj.arr.filter({ (arraySub) -> Bool in
return arraySub.sub_txt.range(of:"Test 2, 2") != nil
}).filter({ (arraySub) -> Bool in
return arraySub.sub_txt.range(of:"Test 2, 2") != nil
})
if internalArray.count > 0 {
return result + [test.init(name: testObj.name, arr: internalArray)]
}else{
return result
}
}
print(news)
Upvotes: 0
Reputation: 54706
A simple filter
won't help you achieve your goals, since you are trying to modify the test
instances as well by filtering their arr
property. You can use compactMap
instead of filter
to return modified test
instances in case they fulfilled the filter
criterion or nil
if they didn't and compactMap
will only keep the non-nil values.
let new = testArr.compactMap({ test->Test? in
let foundArrSub = test.arr.filter({ $0.sub_txt.contains("Test 2, 2") })
if foundArrSub.count > 0 {
return Test(name: test.name, arr: foundArrSub)
}
return nil
})
Test data:
var testArr = [Test]()
testArr.append(Test(name: "Line 1", arr: [ArrSub(sub_txt: "Line 1, 1"), ArrSub(sub_txt: "Line 1, 2")]))
testArr.append(Test(name: "Bell 2", arr: [ArrSub(sub_txt: "Bell 2, 1"), ArrSub(sub_txt: "Bell 2, 2")]))
testArr.append(Test(name: "Bell 2", arr: [ArrSub(sub_txt: "Test 2, 1"), ArrSub(sub_txt: "Test 2, 2"),ArrSub(sub_txt: "Test 2, 23")]))
[__lldb_expr_1.Test(name: "Bell 2", arr: [__lldb_expr_1.ArrSub(sub_txt: "Test 2, 2"), __lldb_expr_1.ArrSub(sub_txt: "Test 2, 23")])]
You should conform to the Swift naming convention, which is UpperCamelCase for types, so I changed test
to Test
and arrSub
to ArrSub
.
Upvotes: 2
Reputation: 743
Thanks, @Dávid Pásztor. I just slightly corrected
let new = testArr.compactMap { (myTest) -> test? in
if let foundArrSub = myTest.arr.first(where: { $0.sub_txt.contains("Test 2, 2") }){
return test(name: myTest.name, arr: [foundArrSub])
}
return nil}
This search will find only one record always in the substructure. But I need to return all the elements that are equal to the search condition.
Upvotes: 0