Merge sub-array in Swift - ios

I have an array and I want to merge it.
This is the array:
let numbers = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
I need a output like this:
let result = [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]

let numbers = [[1,2,3], [4,5,6]]
let result = zip(numbers[0], numbers[1]).map { [$0.0, $0.1]}
print(result) // -> [[1, 4], [2, 5], [3, 6]]
If the array has more elements the following would work.
let numbers = [[1,2,3], [4,5,6], [7,8,9]]
var result : [[Int]] = []
for n in 0...numbers.first!.count-1{
result.append(numbers.compactMap { $0[n] })
}
print(result) // -> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

You can use the zip global function, which, given 2 sequences, returns a sequence of tuples and then obtain an array of tuples by using the proper init.
var xAxis = [1, 2, 3, 4]
var yAxis = [2, 3, 4, 5]
let pointsSequence = zip(xAxis, yAxis)
let chartPoints = Array(pointsSequence)
print(chartPoints)
And then you can access the tuples like this :
let point = chartPoints[0]
point.0 // This is the 1st element of the tuple
point.1 // This is the 2nd element of the tuple

Related

Swift: convert an array into x arrays with n elements each?

I have an array in Swift:
[1, 2, 3, 4, 5, 6, 7, 8]
I need to have X number of arrays each has n elements, say n = 3:
[1, 2, 3], [4, 5, 6], [7, 8]
So that if elements in the end are less than n the last sub-array will have whatever remaining.
I thought about using stride:
let array = [1, 2, 3, 4, 5, 6, 7, 8]
let n = 3
var subarrays = [[Int]]()
for i in stride(from: 0, to: array.count, by: n) {
let slice = array[i..<min(i+n, array.count)]
subarrays.append(Array(slice))
}
I wonder if there's a better way of doing this?
Thanks!

Swift logic - Data structure | Sort the items in Array based on similar number | Interview question [duplicate]

This question already has answers here:
Sort array elements based on their frequency
(8 answers)
Closed 12 months ago.
How to sort an integer array based on a duplicate values count. here less number of duplicates should come first.
input [5, 2, 1, 2, 4, 4, 1, 1, 2, 3, 3, 6]
OutPut [5, 6, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1]
Using Martin's comment, here is another approach which aims to reduce the number of loops and conditions we write ourselves by using some functions provided by swift.
// Input
let numbers = [1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6]
// Count the occurrences based on Martin's comment
let countDict = numbers.reduce(into: [:], { $0[$1, default: 0] += 1 } )
// Get a sorted array of the countDict keys, sorted by value which
// is the number of occurrences
let sortedKeys
= countDict.keys
.sorted { countDict[$0, default: 0] < countDict[$1, default: 0] }
// Initialize an empty array to hold the final sorted numbers
var sortedNumbers: [Int] = []
// Add the elements into the sortedNumbers with in their desired order
for key in sortedKeys {
sortedNumbers.append(contentsOf: repeatElement(key,
count: countDict[key, default: 0]))
}
// prints [5, 6, 4, 4, 3, 3, 1, 1, 1, 2, 2, 2] based on the above input
print(sortedNumbers)
let numbers = [5,2,1,2,4,4,1,1,2,3,3,6]
let sortedNumber = numbers.sorted()
print("Input: ",sortedNumber)
var dict = [Int: Int]()
for item in sortedNumber {
let isExist = dict.contains(where: {$0.key == item})
if !isExist {
dict[item] = 1
} else {
if let value = dict[item] {
dict[item] = value + 1
}
}
}
var finalArray = [Int]()
let sortedArray = dict.sorted { (first, second) -> Bool in
return first.value < second.value
}
for d in sortedArray {
for _ in 1...d.value {
finalArray.append(d.key)
}
}
print("Output: ",finalArray)
Input: [1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6]
Output: [5, 6, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1]

How to convert array of 3 element arrays in to a hash where key is first 2 elements

My problem is that I need to do efficient lookups of if a 2 element array and their corresponding value is nil. So if I have the following arrays:
arr1 = [
[1, 2, 100],
[3, 4, nil],
[5, 6, 101]
]
I want something like
h = {
[1, 2] => 100,
[3, 4] => nil,
[5, 6] => 101
}
So I can do something like:
error = []
arr2 = [
[1,2],
[3,4],
[7,8]
]
arr2.each do |val|
if h.include?(val)
if h[val] == nil
error << "Value is nil"
else
# Do something
end
else
error << "Key doesn't exist"
end
end
Given that overwriting or ignoring duplicates is acceptable per your comment.
You can use Enumerable#each_with_object to iterate the Array and create a Hash like so
arr1 = [
[1, 2, 100],
[3, 4, nil],
[5, 6, 101],
[1, 2, nil],
]
arr1.each_with_object({}) do |(*first_two,last),obj|
obj[first_two] = last
end
#=> {[1, 2]=>nil, [3, 4]=>nil, [5, 6]=>101}
You can ignore duplicates in a similar fashion
arr1.each_with_object({}) do |(*first_two,last),obj|
obj[first_two] = last unless obj.key?(first_two)
end
#=> {[1, 2]=>100, [3, 4]=>nil, [5, 6]=>101}
Explanation:
each_with_object({}) will pass each element of of arr1 to the block along with an object (a Hash in this case)
(*first_two,last),obj - *first_two will collect everything up to last and obj is our Hash
obj[first_two] = last simple Hash key assignment
each_with_object returns the object (obj Hash in this case)
Update as recommended by #Stefan in ruby >= 2.7 you could also use
arr1.to_h {|*first_two,last| [first_two, last] }
This version will overwrite keys
arr1 = [
[1, 2, 100],
[3, 4, nil],
[5, 6, 101]
]
result = {}
arr1.each { |i| result[i.first(2)] = i.last }
=> {[1, 2]=>100, [3, 4]=>nil, [5, 6]=>101}
You can destructure every subarray during mapping and then convert result to hash with Array#to_h method
arr1 = [
[1, 2, 100],
[3, 4, nil],
[5, 6, 101],
[1, 2, nil],
]
arr1.map { |*first_two, last| [first_two, last] }.to_h
# => {[1, 2]=>nil, [3, 4]=>nil, [5, 6]=>101}
Duplicates will be overwritten
In case if you need for two last values as key:
arr.map { |b| { b.shift => b }.invert }

What is the equivalent of this python dictionary in Dart?

What is the equivalent of this python dictionary in Dart?
edges = {(1, 'a') : 2,
(2, 'a') : 2,
(2, '1') : 3,
(3, '1') : 3}
You could use package:collection's EqualityMap to define a custom hash algorithim that uses ListEquality. For example, you could do this:
var map = new EqualityMap.from(const ListEquality(), {
[1, 'a']: 2,
[2, 'a']: 2,
});
assert(map[[1, 'a']] == map[[1, 'a']])
This will be a heavier weight implementation of Map, though.
You have differents way to do this
1. Using a List
var edges = <List, num>{
[1, 'a']: 2,
[2, 'a']: 2,
[2, '1']: 3,
[3, '1']: 3
};
Simple to write, but you won't be able to retrieve data with
edges[[2, 'a']]; // null
Except if you use const
var edges = const <List, num>{
const [1, 'a']: 2,
const [2, 'a']: 2,
const [2, '1']: 3,
const [3, '1']: 3
};
edges[const [2, 'a']]; // 2
2. Using Tuple package
https://pub.dartlang.org/packages/tuple
var edges = <Tuple2<num, String>, num>{
new Tuple2(1, 'a'): 2,
new Tuple2(2, 'a'): 2,
new Tuple2(2, '1'): 3,
new Tuple2(3, '1'): 3
}
edges[new Tuple2(2, 'a')]; // 2
var edges = {[1, 'a'] : 2,
[2, 'a'] : 2,
[2, '1'] : 3,
[3, '1'] : 3};
Except that you won't ever be able to look up those keys, because a new instance of [1, 'a'] will be a different object.

The Swift Programming Language Book Chapter Section on Control Flow Experiment 3

I am working through the first chapter of the book and can't figure out the experiment:
Add another variable to keep track of which kind of number was the
largest, as well as what that largest number was.
This is the code from the book:
let interstingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13, 17],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25, 36],
]
var largest = 0
for (kind, numbers) in interstingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
largest
Like this:
let interstingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13, 17],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25, 36],
]
var largest = 0
var largestKind = ""
for (kind, numbers) in interstingNumbers {
for number in numbers {
if number > largest {
largest = number
largestKind = kind
}
}
}
largest
largestKind
So basically you'd want to put kind somewhere at the same time as you put number into largest, e.g. into a variable called largestKind.
The question asked to keep track of the value and type not to just display the type of the final answer.
I think this gets closer:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var largestType = [String]()
var largestValues = [Int]()
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
largestValues.append(largest)
largestType.append(kind)
}
}
}
print(largest)
print(largestType)
print(largestValues)
And now with tuples:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var largestValues: [(type: String, value: Int)] = []
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
largestValues.append(type: kind, value: number)
}
}
}
print(largest)
print(largestValues)
let interestingNumbers = [ "Prime" : [2,3,5,7,11,13],
"Fibonacci" : [1,1,2,3,5,8,13],
"Square" : [1,4,9,16,25,36],
]
var largest = 0
var largestKind = ""
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
largestKind = kind
}
}
}
print(largest, largestKind)
outputs : 36 Sqaure
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var largestNumbers = [
"Prime":0,
"Fibonacci":0,
"Square":0,
]
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
if(number > largestNumbers[kind]!){
largestNumbers[kind] = number;
}
}
}
print(largest)
print(largestNumbers)
Result is:
25
["Fibonacci": 8, "Square": 25, "Prime": 13]

Resources