Unable to compare lists and array in scala - scala

My problem statement is as below:
1) I have a path till a folder. I have to traverse using that path. Check whether there are any subfolders and files in that path. If yes, match the contents of the folder(Lists) with the array. If it matches take it as a new path.
2) Using new path. List down the files in that path.
I am able to do everything except comparing lists and array. Below is my code:
import java.text.SimpleDateFormat
import java.util.Calendar
import java.io.File
class ListingDirectories {
def getListOfDirectories(dir: String): List[File] = {
val d = new File(dir)
if (d.exists && d.isDirectory) {
d.listFiles().filter(_.isDirectory()).toList
} else {
List[File]()
}
}
def getListOfFiles(dir: String): List[File] = {
val d = new File(dir)
if (d.exists && d.isDirectory()) {
d.listFiles().filter(_.isFile()).toList
} else {
List[File]()
}
}
}
object FirstSample {
def main(args: Array[String]) {
val ld = new ListingDirectories()
val directoriesList = ld.getListOfDirectories("C:/Users/Siddheshk2/Desktop/CENSUS").toList
println(directoriesList + "\n")
val directoriesListReplaced = directoriesList.toString().replace("//", "/")
// println(directoriesListReplaced.indexOf("C:/Users/Siddheshk2/Desktop/CENSUS/SAMPLE"))
var finalString = ""
var s = Array("C:/Users/Siddheshk2/Desktop/CENSUS/SAMPLE")
for (x <- s) {
if (x.equals(directoriesListReplaced)) {
finalString = s(0)
} else {
println("No matching strings")
}
}
val filesList = ld.getListOfFiles(finalString)
println(filesList.toString())
}
}
I just need to compare the values from the list and array and take it as a new path in finalString variable in order to pass in the next method which is getListOfFiles. I figured out since I am returning List[file] in methods I am not able to access the elements inside it. Can anyone help me to understand where am I going wrong? TIA

Your directoriesListReplaced will be a string which looks like "List(C:/Users/Siddheshk2/Desktop/CENSUS/SAMPLE,C:/Users/Siddheshk2/Desktop/CENSUS/SAMPLE1,C:/Users/Siddheshk2/Desktop/CENSUS/SAMPLE2)" and s won't equal it. It isn't at all clear what you want to do with directoriesListReplaced; maybe it should just be
for (x <- s) {
if (directoriesList.contains(x)) {
...
} else {
println("No matching strings")
}
}

After lot of struggle, I solved it using below code:
import java.io.File
object PlayingWithLists {
def main(ar: Array[String]) {
var s = "C:/Users/Siddheshk2/Desktop/CENSUS/SAMPLE2"
var finalValue = ""
var valuesReplaced = ""
var filePath = ""
for (file <- new File("C:/Users/Siddheshk2/Desktop/CENSUS").listFiles) {
valuesReplaced = file.toString.replace("\\", "/")
if (valuesReplaced.contains(s.trim)) {
finalValue = file.toString
} else {
}
}
for (file <- new File(finalValue).listFiles) {
filePath = file.toString.trim
}
}
}

Related

scala return type mismatch of function

I'm just dipping my feet into scala and am stuck on why this method does not compile. I want header to find a file given a directory path and a text file name and return the first n lines of the text file. The compile error I get is:
type mismatch;
found: Unit
required:String
import java.io._
def header(fileName:String, directory:String =".",n:Int=5): String = {
val files = new File(directory).listFiles
for (file <- files if file.getName == fileName) {
val source = scala.io.Source.fromFile(file)
try{
val string=source.getLines.toList.slice(0,n).mkString
string
}
catch {
case e: Exception => "not good. something went wrong"
}
finally{
source.close
}
}
}
Your for loop is not returning the response as you expect. Either you can use mutable variable there and return the variable. (not recommended)
{
...
var response = ""
for (file <- files if file.getName == fileName) {
try {
response = source.getLines.toList.slice(0,n).mkString
}
...
} // end of for
response
}
Or use .filter followed by .map which gives you an Array[String].
def header(fileName:String, directory:String =".",n:Int=5): String = {
val files = new File(directory).listFiles
val response= files.filter(_.getName.equals(fileName)).map { file =>
val source = scala.io.Source.fromFile(file)
val sliced = source.getLines.toList.slice(0,n).mkString
source.close()
sliced
}
response(0)
}

Circular Generators hanging indefinately

I have a set of names in a file. I need to implement a Generator that iterates through them continually. However, the code is hanging indefinitely at if (iter.hasNext) after the first pass.
Gen code
var asStream = getClass.getResourceAsStream("/firstnames/female/en_US_sample.txt")
var source: BufferedSource = Source.fromInputStream(asStream)
var iter: Iterator[String] = Iterator.continually(source.getLines()).flatten
val genLastName: Gen[String] = {
genCannedData
}
def genCannedData: Gen[String] = {
println("Generating names: " + iter)
Gen.delay {
if (iter.hasNext) {
println("In if")
Gen.const(iter.next)
}
else {
println("In else")
Gen.const(iter.next)
}
}
}
Sample Property test
property("FirstNames") = {
forAll(genLastName) {
a => {
println(a)
a == a
}
}
}
en_US_sample.txt file contents
Abbie
Abby
Abigail
Ada
Adah
EDIT- Temporary working code
The following code works if I recreate the iterator but I was wondering why Iterator.continually is hanging?
def genCannedData: Gen[String] = {
Gen.delay {
if (iter.hasNext) {
Gen.const(iter.next)
}
else {
asStream = getClass.getResourceAsStream("/firstnames/female/en_US_sample.txt")
source = Source.fromInputStream(asStream)
iter = source.getLines()
Gen.const(iter.next)
}
}
}
After first iteration, an iterator returned by source.getLines() returns false for hasNext, which means an empty iterator.
Iterator.continually() continually evaluate source.getLines() expecting a next iterator, but it continues to return an empty iterator. Then it forms an infinite loop.

Why is return required in this code block?

Below code just returns a random String via the getFileName method :
import scala.collection.mutable.ListBuffer
object RTest extends App {
var currentFileNameList: ListBuffer[String] = new ListBuffer
def getFileName(): String = {
var fileName = java.util.UUID.randomUUID().toString();
while (true) {
if (!currentFileNameList.contains(fileName)) {
currentFileNameList = currentFileNameList :+ fileName
return fileName
} else {
fileName = java.util.UUID.randomUUID().toString();
}
}
throw new RuntimeException("Error - filename not generated")
}
println(getFileName())
}
If I remove the return statement in line : return fileName then the method getFileName appears to get caught in an infinite loop and does not terminate.
Why is the explicit return required ? Should the scala compiler not infer the return of var fileName ?
As om-nom-nom already said in a comment, it's not really about the type inference, rather it's a control flow problem.
By using return you're breaking the (otherwise) infinite while loop.
Also, not really part of the question, but since you're using a random UUID, you can probably drop the duplicate-checking code and simply return the generated UUID as it is, unless you have insanely high requirements.
According to Wikipedia,
[the probability of generating a duplicate string] is about 0.00000000006 (6 × 10−11), equivalent to the odds of creating a few tens of trillions of UUIDs in a year and having one duplicate.
In a "normal" case I would simply do
def getFileName: String = java.util.UUID.randomUUID.toString
and be done with it.
Because of this block...
while (true) {
if (!currentFileNameList.contains(fileName)) {
currentFileNameList = currentFileNameList :+ fileName
return fileName
} else {
fileName = java.util.UUID.randomUUID().toString();
}
}
You are in an endless loop, as "true" never changes. By returning the function you are jumping out of this loop (as well as completely out of the function).
You could do something like...
object RTest extends App {
var currentFileNameList: ListBuffer[String] = new ListBuffer
def getFileName(): String = {
var fileName = java.util.UUID.randomUUID().toString();
while (currentFileNameList.contains(fileName)) {
fileName = java.util.UUID.randomUUID().toString();
}
currentFileNameList = currentFileNameList :+ fileName;
return fileName;
}
println(getFileName())
}
Which should have the same effect.
No loops, vars, or (explicit) recursion
def getFileName(): String = {
val fileName = Iterator.continually(java.util.UUID.randomUUID().toString())
.find(!currentFileNameList.contains(_)).get
currentFileNameList += fileName
fileName
}
You're not supposed to be looping or using vars:
import scala.collection.mutable.ListBuffer
object Test extends App {
val currentFileNameList: ListBuffer[String] = new ListBuffer
#annotation.tailrec
def getFileName(): String = {
val fileName = java.util.UUID.randomUUID().toString();
if (!currentFileNameList.contains(fileName)) {
currentFileNameList += fileName
fileName
} else {
getFileName()
}
}
println(getFileName())
}

Scala Count Lines in a file VERY FAST

Count lines in a file (With BufferedInputStream) in Scala.
object CountLinesScala {
def main(args: Array[String]) {
val c = countLines("C:/.../Motifs/mrr569.fasta")
println(c)
}
def countLines(filename: String): Int = {
val is = new BufferedInputStream(new FileInputStream(filename))
try {
val c = Array.ofDim[Byte](1024)
var count = 0
var readChars = 0
var empty = true
while ((readChars = is.read(c)) != -1) {
empty = false
for (i <- 0 until readChars if c(i) == '\n') {
count=count +1
}
}
if ((count == 0 && !empty)) 1 else count
} finally {
is.close()
}
}
}
its not working, Why ?
i click run but there is no reaction, and no Errors !
You code is not working because the type of an assignation is Unit and you are comparing Unit to an Int (-1) which can never be equal, therefore your while loop never exits.
More specifically, this expression has type Unit
(readChars = is.read(c))
if you want to fix your version of the program you could define an internal function doRead
def doRead: Int = {
readChars = is.read(c)
readChars
}
and use that in your while loop
while (doRead != -1) {
empty = false
for (i <- 0 until readChars if c(i) == '\n') {
count=count +1
}
}
the final code for countLine would look like
def countLines(filename: String): Int = {
val is = new BufferedInputStream(new FileInputStream(filename))
try {
val c = Array.ofDim[Byte](1024)
var count = 0
var readChars = 0
var empty = true
def doRead: Int = {
readChars = is.read(c)
readChars
}
while (doRead!= -1) {
empty = false
for (i <- 0 until readChars if c(i) == '\n') {
count=count +1
}
}
if ((count == 0 && !empty)) 1 else count
} finally {
is.close()
}
}
However I advise you not to write Scala code like this. As was answered by brian, the most idiomatic way to write this would be to use the scala standard library and write
scala.io.Source.fromFile("C:/.../Motifs/mrr569.fasta").getLines.size
Then your original program would become
import scala.io.Source
object CountLinesScala {
def main(args: Array[String]) {
val c = Source.fromFile("C:/.../Motifs/mrr569.fasta").getLines().size
println(c)
}
}
The standard library handles this nicely.
scala.io.Source.fromFile("C:/.../Motifs/mrr569.fasta").getLines.size

StackOverflowError while using Scala Iterator

I am trying to save a large data set (50MB) into file. But I get the following error:
java.lang.StackOverflowError
at scala.collection.Iterator$$anon$12.hasNext(Iterator.scala:350)
at scala.collection.Iterator$$anon$12.hasNext(Iterator.scala:350)
...
It looks to me like a recursion problem but I can't find where it would come from. Plase help. Function that makes the Iterator[String]:
override def toJsonIterator: Iterator[String] = {
val lastId = listMap.keys.toList.sorted.last
def evalJS(id: Int): String = {
Json.prettyPrint(listMap(id).toJsonValue) + (if(id != lastId) "," else "")
}
listMap.keys.toList.sorted
.foldLeft(Iterator("{"))( (sum, id) => sum ++ Iterator(evalJS(id)) ) ++ Iterator("}")
}
The save to file code:
private def write(st: Iterator[String], file: String): Unit = {
if (st.isEmpty) return ()
val f = new File(file)
if (!f.getParentFile().exists()) f.getParentFile().mkdirs()
if (!f.exists()) f.createNewFile()
val p = new java.io.PrintWriter(f)
try {
while(st.hasNext) {
p.println(st.next())
}
}
catch {
case e:Exception => println("Error: could not write to file \""+file+"\" because: "+e)
}
finally { p.close() }
}