How to adjust function for Iterable Array? - arrays

1974,1974-06-22
1966,1966-07-20
1954,1954-06-19
1994,1994-06-27
1954,1954-06-26
2006,2006-07-04
2010,2010-07-07
1990,1990-06-30
...
It is type RDD[String].
What is wrong in the function iteself?

Try
def f(v: Iterable[Array[String]]): Int = {
val parsedDates = v.flatten.map(e => LocalDate.parse(e, formatter))
parsedDates.max.getDayOfYear - parsedDates.min.getDayOfYear
}
which outputs
val arrays = Iterable(Array("2014-10-10","2014-12-10"))
f(arrays) // res0: Int = 61

Related

Can I create array by for loop in Kolin? the array is list listOfNames is inside a for loop but I can not use it outside the for loop

Can I create array by for loop in Kolin? the array is the list [listOfNames] is inside a for loop but I can not use it outside the for loop. I have to get strings from Excel in to array list and use it in main method.
fun readFromExcelFile(filepath: String): ArrayList<String> {
var listOfNames = ArrayList<String>()
val inputStream = FileInputStream(filepath)
var xlWb = WorkbookFactory.create(inputStream)
val rowNumber = 0
val columnNumber = 0
val xlWs = xlWb.getSheetAt(0)
for (i in 0..10) {
var currentCell = xlWs.getRow(i).getCell(columnNumber)
//println(currentCell)
listOfNames.add(currentCell.stringCellValue)
println(listOfNames)
}
//println(listOfNames)
return listOfNames
}
I would recommend that you return a List instead of an ArrayList and populate a MutableList in your function:
fun readFromExcelFile(filepath: String): List<String> {
var names = mutableListOf<String>()
val inputStream = FileInputStream(filepath)
var xlWb = WorkbookFactory.create(inputStream)
val rowNumber = 0 // you don't use this.
val columnNumber = 0
val xlWs = xlWb.getSheetAt(0)
for (i in 0..10) { // why isn't the range over the # of rows in the worksheet?
var currentCell = xlWs.getRow(i).getCell(columnNumber)
names.add(currentCell.stringCellValue)
}
return names
}

Iterating through references to variables in Swift

I am looking for a way to change the values of multiple variables using iteration in Swift. An example would be something like this:
var a = false
var b = false
var c = false
func makeAllTrue() {
for n in [a, b, c] {
n = true
}
}
...but rather than an array of values, I want to iterate through an array of pointers/references to the variables above.
Any advice would be greatly appreciated.
var a = false
var b = false
var c = false
mutateValues(&a, &b, &c) { n in
n = true
}
print(a, b, c) // will be printed "true true true"
func mutateValues<Value>(_ values: UnsafeMutablePointer<Value>..., mutate: (inout Value) -> Void) {
values.forEach {
mutate(&$0.pointee)
}
}
It is possible to do this with key paths. Let's say the properties are in a class Foo:
class Foo {
var a = false
var b = false
var c = false
func makeAllTrue() {
for n in [\Foo.a, \Foo.b, \Foo.c] {
self[keyPath: n] = true
}
}
}
If Foo is a struct, use mutating func instead:
struct Foo {
var a = false
var b = false
var c = false
mutating func makeAllTrue() {
for n in [\Foo.a, \Foo.b, \Foo.c] {
self[keyPath: n] = true
}
}
}
However, if the class name is long, I don't think it is worth doing this way.
If these three properties are very related, I would not bother with the key path stuff and replace a, b and c with an array:
var abc = [false, false, false]
and have the for loop loop over the indices:
for i in abc.indices {
abc[i] = true
}
An Array in Swift is a struct, hence a value type.
Iterating over his children, and changing one, will not be possible unless:
The type of child is aa class (which is reference typed)
You iterate over the indices and change the real values!
E.G:
var a: Int = 1
var b: Int = 2
var array: [Int] = [a,b]
for index in array.indices {
array[index] += 1
}
print(array) // [2,3]

Does Swift offer any built-in function to return the result of appending to an immutable array?

Writing the question and answer from here, I'm curious to know if there is any simpler way to write the following:
var nums = [1,2,3]
let sum1 = nums.reduce([Int]()){
let temp = $0
temp.append($1)
return temp
}
I know I can do:
var nums = [1,2,3]
let sum1 = nums.reduce([Int]()){
return $0 + [$1]
}
But that comes off as a hack.
To explain this better, I want to get closer to the example (from docs) below, just that it should be for an array:
let numbers = [1, 2, 3, 4]
let numberSum = numbers.reduce(0, { x, y in
x + y
})
EDIT:
Since folks asked what was I trying to achieve:
I was doing the leetcode's group Anagram's challenge.
My solution was:
struct WordTraits: Equatable{
let count: Int
let charactersSet: Set<Character>
}
struct Word: Equatable{
let string: String
let wordTraits: WordTraits
}
class Solution{
func groupAnagrams(_ strs: [String]) -> [[String]]{
var words : [Word] = []
var answers : [(traits: WordTraits, words: [Word])] = []
var count = 0
strs.forEach{ str in
count += 1
let count = str.count
let string = str
let characterSet = Set(str)
let wordTraits = WordTraits(count: count, charactersSet: characterSet)
let word = Word(string: string, wordTraits: wordTraits)
words.append(word)
}
while words.count != 0{
let word = words[0]
let traits = word.wordTraits
var isWordAdded = false
for (i, answer) in answers.enumerated(){
if answer.traits == traits{
answers[i].words.append(word)
isWordAdded = true
break
}
}
if !isWordAdded{
answers.append((traits: traits, words:[word]))
}
words.removeFirst()
}
let emptyArray : [[String]] = []
let finalAnswer = answers.reduce(emptyArray, { total, answer in
let strings : [String] = answer.words.reduce([String](), {
return $0 + [$1.string]
})
return total + [strings]
})
return finalAnswer
}
}
let s = Solution()
print(s.groupAnagrams(["ate", "eta", "beta", "abet"])) // [["ate", "eta"], ["beta", "abet"]]
reduce(..) has to know which type it is working with. To infer this it can use the return type or the type of the first argument. So you can also write:
var nums = [1,2,3]
let sum1: [Int] = nums.reduce([]){
return $0 + [$1]
}
[$1] can't be replaced with $1 because +-operator between value and collection is undefined.
Nope. But you can add it:
extension Array {
func appending(_ newElement: Element) -> Array<Element> {
return self + [newElement]
}
func appending(contentsOf sequence: Sequence) -> Array<Element> {
return self + sequence
}
}
Um, how about the + operator?
let nums = [1, 3, 5]
let more = nums + [7]
Your code is trying to convert a complex structure to an array of arrays. You can use map for this.
This should work:
let finalAnswer = answers.map { answer in
answer.words.map {
$0.string
}
}
Edit:
I was able to solve it using minimal code:
class Solution {
func groupAnagrams(_ words: [String]) -> [[String]] {
let processedWords = words.map {
(key: String($0.sorted()), value: $0)
}
return Dictionary(grouping: processedWords, by: { $0.key }).map { groupedValue in
groupedValue.value.map {
$0.value
}
}
}
}
You've greatly overcomplicated your computation of "final answers". It could just be:
return answers.map { $0.words.map { $0.string } }

How can I split array elements in arrays in Swift?

For example consider following array:
var array = [1,[2,3],5]
I want result in following way:
a = [1]
b = [2,3]
c = [5]
You can split an array into chunks:
If you have an array of elements and you want to split them into chunks of a size you specify.
Example:
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
let numbers = Array(1...100)
let result = numbers.chunked(into: 5)
Now you can access first second and your index object from the result like:
let a = result.first // [1]
let array = [1,[2,3],5]
let a = [array[0]]
let b = [array[1]]
let c = [array[2]]

Kotlin 2d Array initialization

Please take a look at my 2D-Array-Initialization. The code works.
class World(val size_x: Int = 256, val size_y: Int = 256) {
var worldTiles = Array(size_x, { Array(size_y, { WorldTile() }) })
fun generate() {
for( x in 0..size_x-1 ) {
for( y in 0..size_y-1 ) {
worldTiles[x][y] = WorldTile()
}
}
}
}
The problem is that it runs the initialization twice. Basically I want to instantiate the WorldTile-Object in the generate() function. So Line 3 shouldn't call "new WorldTile" there. How can I do that?
Also is that the proper Kotlin way of traversing a 2d-Array?
You can make worldTiles a lateinit property, and do all the initialization in the generate function:
class World(val size_x: Int = 256, val size_y: Int = 256) {
lateinit var worldTiles: Array<Array<WorldTile>>
fun generate() {
worldTiles = Array(size_x, {
Array(size_y, {
WorldTile()
})
})
}
}
If you try to access worldTiles before calling generate you will get an exception warning that it hasn't been initialized yet.
To initialise all to a fixed value:
// A 6x5 array of Int, all set to 0.
var m = Array(6) {Array(5) {0} }
To initialise with a lambda:
// a 6x5 Int array initialise i + j
var m = Array(6) { i -> Array(5) { j -> i + j } }
Another way: Here is an example of initialising a 2D array of Float numbers (3 by 6):
var a = Array(3) { FloatArray(6)} // define an 3x6 array of float numbers
for(i:Int in 0 until a.size) {
for(j : Int in 0 until a[i].size) {
a[i][j] = 0f // initialize with your value here.
}
}
val twoDimStringArray= arrayOf(
arrayOf("first","second"),
arrayOf("foo"),
arrayOf("bar","great kotlin")
)
for (i in twoDimStringArray){
for(j in i){
println(j)
}
}
first
second
foo
bar
great kotlin
A bit late but could help to somebody if is working with strings
//init 2d array with a fixed size:
var data2 = Array<Array<String>>(2) { arrayOf()}
// fill the 2d array
data2[0] = arrayOf("123","Freddy x","27")
data2[1] = arrayOf("124","Elon y","45")
cheers!

Resources