I have a folder that has a many files in it. somewhat between 1000 and 15000.
I would need to randomly pick 1000 files from this folder and copy it over to another folder.
I know how to get a single random file from a folder by inserting the list of files in an array and then selecting one randomly, but dont know how to get many while avoiding to select the same file twice.
If for example I have 1001 file in my folder, it will have no trouble getting the fist few, but then towards the end, it is very likely to pick a file that has already been copied over and it would take many tries to find for example the last file just by luck...
my first idea was to divide the number of files by 1000. so for example 1500/1000 = 1.5. and then create a random integer between 0 and 1.5. this would return 1. then do the next rand between nth image and nth image * 1.5.
if the folder hast 15000 files, it would pick the first file randomly between 1 and 15, and then between 6 and 30 and so on..
but there must be a smarter solution for this..
any help appreciated
You can order them randomly:
Dim allFiles = Directory.EnumerateFiles("path")
Dim rnd As New Random()
Dim random1000 = From f In allfiles
Order By rnd.Next()
Select f
Take 1000
Dim list = random1000.ToList()
This is using System.Linq
Using indices into the list of files
Private Shared prng As New Random
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ListOfiles() As String = IO.Directory.GetFiles(BasePath)
Dim indices As IEnumerable(Of Integer)
indices = Enumerable.Range(0, ListOfiles.Length).OrderBy(Function() prng.Next).Take(1000)
For Each idx As Integer In indices
Dim fn As String = ListOfiles(idx)
Stop
Next
End Sub
Related
Don't know really how to go about this? I can convert one tif to one pdf. I can convert all tifs in one directory into one pdf. What I want to do is convert a group of tifs based on their lastwriteaccess or createddate or modifieddate.
For example, if I have 7 tifs in one directory where 3 have the same timestamp and 4 have another same timestamp, I want to merge the 3 into one pdf then merge the other 4 into another pdf. I'm kind of stuck on how to approach this. Do I need to create list of all the files then group them or can I merge 3 then go the next group merge those etc, etc, etc using a for each?
The code below is what I'm using to collect the first 5 files:
Dim dir As New DirectoryInfo(tiffPath)
Dim files As List(Of FileInfo) =
dir.GetFiles("*.tif").OrderByDescending(Function(fc)
fc.LastAccessTime).Take(5).ToList
For Each lfi As FileInfo In files
MsgBox(lfi.Name)
Next
It looks like it would be sufficient to bunch files together if their timestamps differ by less than some timespan.
So, if you order the files by their .LastWriteTimeUtc then you can iterate over that list and check how long it was between one and the previous one. If the gap is small then add it to the current list, otherwise start a new list.
I tested the following code on a directory with a random selection of files, so 30 days was an appropriate timespan for that, it looks like maybe two or three seconds would be good for your use:
Option Infer On
Option Strict On
Imports System.IO
Module Module1
''' <summary>
''' Get FileInfos bunched by virtue of having less than some time interval between their consecutive LastWriteTimeUtc when ordered by that.
''' </summary>
''' <param name="srcDir">Directory to get files from.</param>
''' <param name="adjacencyLimit">The allowable timespan to count as in the same bunch.</param>
''' <returns>A List(Of List(Of FileInfo). Each outer list has consecutive LastWriteTimeUtc differences less than some time interval.</returns>
Function GetTimeAdjacentFiles(srcDir As String, adjacencyLimit As TimeSpan) As List(Of List(Of FileInfo))
Dim di = New DirectoryInfo(srcDir)
Dim fis = di.GetFiles().OrderBy(Function(fi) fi.LastWriteTimeUtc)
If fis.Count = 0 Then
Return Nothing
End If
Dim bins As New List(Of List(Of FileInfo))
Dim thisBin As New List(Of FileInfo) From {(fis(0))}
For i = 1 To fis.Count - 1
If fis(i).LastWriteTimeUtc - fis(i - 1).LastWriteTimeUtc < adjacencyLimit Then
thisBin.Add(fis(i))
Else
bins.Add(thisBin)
thisBin = New List(Of FileInfo) From {fis(i)}
End If
Next
bins.Add(thisBin)
Return bins
End Function
Sub Main()
Dim src = "E:\temp"
'TODO: choose a suitable TimeSpan, e.g. TimeSpan.FromSeconds(3)
Dim adjacencyLimit = TimeSpan.FromDays(30)
Dim x = GetTimeAdjacentFiles(src, adjacencyLimit)
For Each b In x
Console.WriteLine("***********")
For Each fi In b
'TODO: merge each fi into a PDF.
Console.WriteLine(fi.Name)
Next
Next
Console.ReadLine()
End Sub
End Module
I suggest two or three seconds because if the files have been stored on a FAT-type (e.g. FAT32 or exFAT, as can be used on USB memory sticks, old disk drives, and such) filesystem then the resolution of the timestamp will have been two seconds.
I'm writing a program that creates new folders and moves the old folder to an archive location.
I need to be able to compare the last three digits of a folder path to see if it's "999", for example a folder will be called "1950-1999" and this will need a new parent folder.
Code so far:
Dim stringreader As String
Dim path As List(Of String)
Private Sub Archive_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Loads a text file at the given location, to read to.
fileReader = My.Computer.FileSystem.OpenTextFileReader("C:\Data\Test\Foldercreation.txt")
'Set stringreader as the read line from the file
stringreader = fileReader.ReadLine()
path = System.IO.Directory.GetDirectories(stringreader).ToList
path.Sort()
foldtoarchtxt.Text = path(0)
'closes the file
fileReader.Close()
As you can see I have got the folder path and stored it in a list (which is displayed to the user as well hence the text output).
I just don't know how to get VB.NET to always look at the last three digits on the right. One note, this will get to 100000's and maybe even 1000000 i.e. 100950-100999 so it can't be based on position from the left.
Consider using String.Substring:
Retrieves a substring from this instance. The substring starts at a specified character position and continues to the end of the string.
If path(0).Substring(path(0).Length - 3)) = "999" Then
...
End If
As an example:
Dim s As String = "100950-100999"
Debug.WriteLine(s.Substring(s.Length - 3))
Output:
999
You can use Strings.Right(string, n) to get the last n characters of string:
Returns a string containing a specified number of characters from the right side of a string.
Is there a simple solution to select random strings in vb.net? I have a list of about twenty paragraphs where three need to go after each other and I want it to be random. Do I have to create a variable? Or is there a command that can be run on a button click?
One (fairly easy way) to accomplish this would be to have a collection of the paragraphs you want to use, and then use PeanutButter.RandomValueGen from the Nuget package PeanutButter.RandomGenerators (it's open-source too)
RandomValueGen.GetRandomFrom takes a collection of anything and returns a random item from the collection. As a bonus, you can specify a params list of values not to pick, so you can ensure that your paragraphs aren't repeated.
Whilst the library is written in C#, it can obviously be used from any .NET project. There are a lot of other generator methods on RandomValueGen too, if you're interested.
Full disclosure: I'm the author.
If you have a normal list, this should work:
If not, write what kind of list you have.
Dim rn As New Random
Dim selct As String = lst(rn.Next(0, lst.Count - 1))
selct is the output.
Replace lst with your list name.
if you don't want to have a dependency or need to stay on 4.0 for some odd reason or reason X, you can always try this instead
Private rnd As New Random
Public Function GetRandom(input As IEnumerable(Of String), itemToGet As Integer) As List(Of String)
If input.Count < itemToGet Then
Throw New Exception("List is too small")
End If
Dim copy = input.ToList
Dim result As New List(Of String)
Dim item As Integer
While itemToGet > 0
item = rnd.Next(0, copy.Count)
result.Add(copy(item))
copy.RemoveAt(item)
itemToGet -= 1
End While
Return result
End Function
I'm trying to use multiple random variables for something I'm making in Visual Studio. This is the code.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Declaring random variables
Dim cC1 As New Random
Dim cC2 As New Random
Dim cC3 As New Random
Dim cC4 As New Random
Dim cC5 As New Random
Dim cCard1 As New Integer
cCard1 = cC1.Next(1, 14)
Dim cCard2 As New Integer
cCard2 = cC2.Next(1, 14)
Dim cCard3 As New Integer
cCard3 = cC3.Next(1, 14)
Dim cCard4 As New Integer
cCard4 = cC4.Next(1, 14)
Dim cCard5 As New Integer
cCard5 = cC5.Next(1, 14)
'Computers random choice
Dim x As New Integer
Dim s As New Random
x = s.Next(1, 14)
There's a bit more but it's basically a duplicate. The issue is that these "random" variables are ALL the same. I thought that the error might have been because the code was like so:
Dim cCard1 = cC1.Next(1, 14)
I have written another program which executes what I wanted with the exact same code, while this programs variables aren't all too random. :(
After changing it to the current code, the issue is still prominent and I'm looking for an explanation to why this occurs, and more importantly, a way to correct this error. Any form of help will be highly appreciated!
That is because when you create the Random instance, it uses the current time as its seed. The seed is a number that, when identical, yields the exact same sequence of pseudo-random numbers. In your case this happens fast enough that all instances share the same seed and thus all yield the same first number.
You should create one Random instance and get multiple numbers from it instead.
I need to select a file from a directory and move to another directory. In order to do that I need to select a file randomly.
I need to select a random file (any ext can be) but I dont know how to use return because I am new to VB.NET. So please give ideas and code.
Like this?
Sub MoveRandomFile(from$, to$)
Static r As New Random
Dim Files = New IO.DirectoryInfo([from]).GetFiles
Dim FileToMove = Files(r.Next(0, Files.Count))
IO.File.Move(FileToMove.FullName, FileToMove.FullName.Replace([from], [to]))
End Sub
Or if you just want to return a random file:
Function GetRandomFile(folder$) As IO.FileInfo
Static r As New Random
Dim Files = New IO.DirectoryInfo(folder).GetFiles
Return Files(r.Next(0, Files.Count))
End Function
The static keyword creates the variable the first time the method is called, and keeps it for the next time.
The reason we need to do that is because the random object uses a seed, like in Minecraft, and this seed is generated using information about the running process. So if you create a new random object each time it will choose the same file each time.