gozzilli
gozzilli

Reputation: 8337

Nested array comprehension in Julia

I'm trying to get a list of files with the new walkdir function in Julia. The following works, but I would like the result to be a flat list of files. Can this be achieved with array comprehension, without flattening the array after it has been created?

files = [[joinpath(root, file) for file in files] for (root, dirs, files) in collect(walkdir(AUDIO_PATH))]

Upvotes: 3

Views: 835

Answers (3)

HarmonicaMuse
HarmonicaMuse

Reputation: 7893

As @Daniel Høegh points out, it seems you can't. But you can flatten it easily with the vcat function:

all_files(path::AbstractString) = vcat([[joinpath(root, file) for file in files] for (root, dirs, files) in collect(walkdir(path))]...)

This other more readable version is like Daniel's iterator/generator, but using the cartesian product for loop syntax, alternative @task macro (just to show example of it) and the compact assignment function definition syntax:

function each_file(path::AbstractString)
    iter() = for (root, dirs, files) in walkdir(path), file in files
        produce(joinpath(root, file))
    end
    @task iter()
end

# No need to flatten anything:
all_files(path::AbstractString) = collect(each_file(path))

for file in each_file(AUDIO_PATH)
    @show file
end    

audio_files = all_files(AUDIO_PATH)

Upvotes: 1

Dan Getz
Dan Getz

Reputation: 18217

An option without comprehension but readable (to my human neuralware):

filelist = AbstractString[]
for (root, dirs, files) in walkdir(AUDIO_PATH)
    append!(filelist,map(_->joinpath(root,_),files))
end

Anonymous functions and map may incur performance cost but this should be of smaller importance in file mapping code compared to readability.

Upvotes: 0

Daniel Høegh
Daniel Høegh

Reputation: 716

As far as I know this can not solved with an array comprehension, without flattening the array after it has been created. But you could define a function which iterates over walkdir as:

function files_func(path)
    function it()
        for (root, dirs, files) in walkdir(path)
            for file in files
                produce(joinpath(root,file))
            end
        end
    end
    Task(it)
end

When this function is defined a list of the files can be obtained by collect(files_func(AUDIO_PATH)). Alternatively a list of files can be obtained by looping over walkdir as:

allfiles=ASCIIString[]
for (root, dirs, files) in walkdir(path)
   for file in files
       push!(allfiles,joinpath(root,file))
   end
end
allfiles

Upvotes: 2

Related Questions