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 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
}
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]
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 } }
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]]
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!