Jump to content
Sign in to follow this  
myspacee

Make oreder in text file...

Recommended Posts

myspacee

hello to all,

i've a request.

i've one scrambled file with a lot of lines.

every lines contain words and A number (always different)

is possible to make order in lines based on its number? ES:

________________ A.txt

mouse;9

dog;5

cat;7

________________ B.txt <------ ordered

dog;5

cat;7

mouse;9

thank you for any info and idea

m.

(this task is for job)

Share this post


Link to post
Share on other sites
PsaltyDS

hello to all,

i've a request.

i've one scrambled file with a lot of lines.

every lines contain words and A number (always different)

is possible to make order in lines based on its number? ES:

________________ A.txt

mouse;9

dog;5

cat;7

________________ B.txt <------ ordered

dog;5

cat;7

mouse;9

thank you for any info and idea

Read A.txt into an array with _FileReadToArray().

ReDim it to a 2D array, [$n][0] will be the original line.

Run a For/Next loop to walk through the array setting [$n][1] to the extracted number from each line.

Run _ArraySort() and sort on the second index = 1 (use Beta).

Run a For/Next loop to write the [$n][0] lines back to B.txt.

If you get stuck, post your code for more help.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
zackrspv

Read A.txt into an array with _FileReadToArray().

ReDim it to a 2D array, [$n][0] will be the original line.

Run a For/Next loop to walk through the array setting [$n][1] to the extracted number from each line.

Run _ArraySort() and sort on the second index = 1 (use Beta).

Run a For/Next loop to write the [$n][0] lines back to B.txt.

If you get stuck, post your code for more help.

:)

Question for you,

I've seen the _ArraySort() functions within beta, but they return values incorrectly:

1: mouse
10: cat
11: dog
12: mouse
13: dino
14: ferrett
15: rodent
15: cat
16: bird
18: horse
2: fish
22: fish
3: dino
4: ferrett
5: rodent
6: bird
8: horse
9: dog

Why is that?

Code:

#include <file.au3>
#include <array.au3>

Local $file = @ScriptDir & "\order.txt"
If Not FileExists($file) Then 
    MakeFile()
Else
    FileOpen($file, 2)
    FileClose($file)
    MakeFile()
EndIf

$lines = _FileCountLines($file)
$lines += 1
Dim $temp[$lines][2]
Dim $Order

If Not _FileReadToArray($file, $Order) Then
    MsgBox(4096, "Error", "Error reading log to array; ===>Error: " & @error)
    Exit
EndIf

$nOffset = 1
For $i = 1 To UBound($Order) -1
    $array = StringRegExp($Order[$i], '(?i)(?s)(.*?);(.*?\z)', 1, $nOffset)
    If @error = 1 Then
    Else
        $temp[$i][0] = $array[1]
        $temp[$i][1] = $array[0]
    EndIf
Next

_ArraySort($temp)
_ArrayDisplay($temp)

Func MakeFile()
    FileWrite($file, "dog1;9"&@CRLF)
    FileWrite($file, "cat2;10"&@CRLF)
    FileWrite($file, "mouse3;1"&@CRLF)
    FileWrite($file, "dino4;3"&@CRLF)
    FileWrite($file, "fish5;2"&@CRLF)
    FileWrite($file, "horse6;8"&@CRLF)
    FileWrite($file, "bird7;6"&@CRLF)
    FileWrite($file, "ferrett8;4"&@CRLF)
    FileWrite($file, "rodent9;5"&@CRLF)
    FileWrite($file, "dog10;11"&@CRLF)
    FileWrite($file, "cat11;15"&@CRLF)
    FileWrite($file, "mouse12;12"&@CRLF)
    FileWrite($file, "dino13;13"&@CRLF)
    FileWrite($file, "fish14;22"&@CRLF)
    FileWrite($file, "horse15;18"&@CRLF)
    FileWrite($file, "bird16;16"&@CRLF)
    FileWrite($file, "ferrett17;14"&@CRLF)
    FileWrite($file, "rodent18;15")
EndFunc
Edited by zackrspv

-_-------__--_-_-____---_-_--_-__-__-_ ^^€ñ†®øÞÿ ë×阮§ wï†høµ† ƒë@®, wï†høµ† †ïmë, @ñd wï†høµ† @ †ïmïdï†ÿ ƒø® !ïƒë. €×阮 ñø†, bµ† ïñ§†ë@d wï†hïñ, ñ@ÿ, †h®øµghøµ† †hë 맧ëñ§ë øƒ !ïƒë.

Share this post


Link to post
Share on other sites
zackrspv

Question for you,

I've seen the _ArraySort() functions within beta, but they return values incorrectly:

1: mouse
10: cat
11: dog
12: mouse
13: dino
14: ferrett
15: rodent
15: cat
16: bird
18: horse
2: fish
22: fish
3: dino
4: ferrett
5: rodent
6: bird
8: horse
9: dog

Why is that?

Resolved, New Code (for me at least), thanks to Siao at least: _ArraySortClib() method.

#include <file.au3>
#include <array.au3>

Local $file = @ScriptDir & "\order.txt"
If Not FileExists($file) Then 
    MakeFile()
Else
    FileOpen($file, 2)
    FileClose($file)
    MakeFile()
EndIf

$lines = _FileCountLines($file)
$lines += 1
Dim $temp[$lines][2]
Dim $Order

If Not _FileReadToArray($file, $Order) Then
    MsgBox(4096, "Error", "Error reading log to array; ===>Error: " & @error)
    Exit
EndIf

$nOffset = 1
For $i = 1 To UBound($Order) -1
    $array = StringRegExp($Order[$i], '(?i)(?s)(.*?);(.*?\z)', 1, $nOffset)
    If @error = 1 Then
    Else
        $temp[$i][0] = $array[1]
        $temp[$i][1] = $array[0]
    EndIf
Next

_ArraySortClib($temp, 0, False, 0, 0, 0)

FileOpen($file, 2)
FileClose($file)
For $i = 1 To UBound($temp) -1
    FileWrite($file, $temp[$i][0]&";"&$temp[$i][1]&@CRLF)
Next
ShellExecute("Notepad")


Func MakeFile()
    FileWrite($file, "dog1;9"&@CRLF)
    FileWrite($file, "cat2;10"&@CRLF)
    FileWrite($file, "mouse3;1"&@CRLF)
    FileWrite($file, "dino4;3"&@CRLF)
    FileWrite($file, "fish5;2"&@CRLF)
    FileWrite($file, "horse6;8"&@CRLF)
    FileWrite($file, "bird7;6"&@CRLF)
    FileWrite($file, "ferrett8;4"&@CRLF)
    FileWrite($file, "rodent9;5"&@CRLF)
    FileWrite($file, "dog10;11"&@CRLF)
    FileWrite($file, "cat11;15"&@CRLF)
    FileWrite($file, "mouse12;12"&@CRLF)
    FileWrite($file, "dino13;13"&@CRLF)
    FileWrite($file, "fish14;22"&@CRLF)
    FileWrite($file, "horse15;18"&@CRLF)
    FileWrite($file, "bird16;16"&@CRLF)
    FileWrite($file, "ferrett17;14"&@CRLF)
    FileWrite($file, "rodent18;15")
EndFunc


;#
;   _ArraySortClib() v3, by Siao
;        Sort 1D/2D array using qsort() from C runtime library (msvcrt.dll, shipped with Windows since Win98 at least)
;   Parameters:
;        $Array - the array to be sorted, ByRef
;        $iMode - sort mode, can be one of the following:
;              0 = numerical, using double precision float compare
;              1 = string compare, case insensitive (default)
;              2 = string compare, case sensitive
;        $fDescend - sort direction. True = descending, False = ascending (default)
;        $iStart - index of starting element (default 0 = $array[0])
;        $iEnd - index of ending element (default 0 = Ubound($array)-1)
;        $iColumn - index of column to sort by (default 0 = first column)
;        $iWidth - max string length of array element to compare (ignored for now)
;   Return values:
;        -1 = dll error
;        0 = sort impossible because
;              @error 0 = nothing to sort
;              @error 1 = invalid array
;              @error 2 = invalid param
;        1 = success
;#
Func _ArraySortClib(ByRef $Array, $iMode = 1, $fDescend = False, $iStart = 0, $iEnd = 0, $iColumn = 0, $iWidth = 0)
    If @AutoItX64 Then Return SetError(666, 0, 0)
    Local $iArrayDims = UBound($Array, 0)
    If @error Or $iArrayDims > 2 Then Return SetError(1, 0, 0)
    Local $iArraySize = UBound($Array, 1), $iColumnMax = UBound($Array, 2)
    If $iArraySize < 2 Then Return 0
    If $iEnd < 1 Or $iEnd > $iArraySize - 1 Then $iEnd = $iArraySize - 1
    If ($iEnd - $iStart < 2) Then Return SetError(2, 0, 0)
    If $iArrayDims = 2 Then
        If ($iColumnMax - $iColumn < 0) Then Return SetError(2, 0, 0)
    EndIf
    If $iWidth < 0 Then Return SetError(2, 0, 0)
    $iWidth = 8
    Local $tSource, $tIndex, $i, $j, $iCount = $iEnd - $iStart + 1, $fNumeric, $fCase, $aRet, $hMsvcrt, $sStrCmp, $tFloatCmp, $pCmp, $tCmpWrap
    Switch $iMode
        Case 0
            $fNumeric = True
        Case 1
            $fCase = False
        Case 2
            $fCase = True
        Case Else
            Return SetError(2, 0, 0)
    EndSwitch
   ;; initialize compare proc
    If $fNumeric Then
        $tFloatCmp = DllStructCreate('byte[36]')
        DllStructSetData($tFloatCmp, 1, '0x8B4C24048B542408DD01DC1ADFE0F6C440750D80E441740433C048C333C040C333C0C3')
        $pCmp = DllStructGetPtr($tFloatCmp)
    Else
        $sStrCmp = "_strcmpi";case insensitive
        If $fCase Then $sStrCmp = "strcmp";case sensitive
        $aRet = DllCall('kernel32.dll', 'hwnd', 'LoadLibraryA', 'str', 'msvcrt.dll')
        $hMsvcrt = $aRet[0]
        $aRet = DllCall('kernel32.dll', 'ptr', 'GetProcAddress', 'ptr', $hMsvcrt, 'str', $sStrCmp)
        DllCall('kernel32.dll', 'hwnd', 'FreeLibrary', 'hwnd', $hMsvcrt)
        If $aRet[0] = 0 Then Return -1
        $pCmp = $aRet[0]
    EndIf
    $tCmpWrap = DllStructCreate('byte[32]')
    DllStructSetData($tCmpWrap, 1, '0xBA' & Hex(Binary($pCmp), 8) & '8B4424088B4C2404FF30FF31FFD283C408C3')
   ;; write data to memory
    If $fNumeric Then
        $tSource = DllStructCreate('double[' & $iCount & ']')
        If $iArrayDims = 1 Then
            For $i = 1 To $iCount
                DllStructSetData($tSource, 1, $Array[$iStart + $i - 1], $i)
            Next
        Else
            For $i = 1 To $iCount
                DllStructSetData($tSource, 1, $Array[$iStart + $i - 1][$iColumn], $i)
            Next
        EndIf
    Else
        Local $sMem = ""
        If $iArrayDims = 1 Then
            For $i = $iStart To $iEnd
                $sMem &= $Array[$i] & Chr(0);safer: $sMem &= StringLeft($Array[$i],4095) & Chr(0)
            Next
        Else
            For $i = $iStart To $iEnd
                $sMem &= $Array[$i][$iColumn] & Chr(0);safer: $sMem &= StringLeft($Array[$i][$iColumn],4095) & Chr(0)
            Next
        EndIf
        $tSource = DllStructCreate('byte[' & StringLen($sMem) + 1 & ']')
        DllStructSetData($tSource, 1, $sMem)
        $sMem = 0
    EndIf
   ;; index data
    $tIndex = DllStructCreate('int[' & $iCount * 2 & ']')
    Local $tEnumProc = DllStructCreate('byte[64]')
    If $fNumeric Then
        DllStructSetData($tEnumProc, 1, '0x8B7424048B7C24088B4C240C8B442410893789470483C60883C708404975F1C21000')
    Else
        DllStructSetData($tEnumProc, 1, '0x8B7424048B7C24088B4C240C8B542410893789570483C7088A064684C075F9424975EDC21000')
    EndIf
    DllCall('user32.dll', 'uint', 'CallWindowProc', 'ptr', DllStructGetPtr($tEnumProc), 'ptr', DllStructGetPtr($tSource), 'ptr', DllStructGetPtr($tIndex), 'int', $iCount, 'int', $iStart)
   ;; sort
    DllCall('msvcrt.dll', 'none:cdecl', 'qsort', 'ptr', DllStructGetPtr($tIndex), 'int', $iCount, 'int', $iWidth, 'ptr', DllStructGetPtr($tCmpWrap))
   ;; read back the result
    Local $aTmp = $Array, $iRef
    If $iArrayDims = 1 Then; 1D
        If $fDescend Then
            For $i = 0 To $iCount - 1
                $iRef = DllStructGetData($tIndex, 1, $i * 2 + 2)
                $Array[$iEnd - $i] = $aTmp[$iRef]
            Next
        Else; ascending
            For $i = $iStart To $iEnd
                $iRef = DllStructGetData($tIndex, 1, ($i - $iStart) * 2 + 2)
                $Array[$i] = $aTmp[$iRef]
            Next
        EndIf
    Else; 2D
        If $fDescend Then
            For $i = 0 To $iCount - 1
                $iRef = DllStructGetData($tIndex, 1, $i * 2 + 2)
                For $j = 0 To $iColumnMax - 1
                    $Array[$iEnd - $i][$j] = $aTmp[$iRef][$j]
                Next
            Next
        Else; ascending
            For $i = $iStart To $iEnd
                $iRef = DllStructGetData($tIndex, 1, ($i - $iStart) * 2 + 2)
                For $j = 0 To $iColumnMax - 1
                    $Array[$i][$j] = $aTmp[$iRef][$j]
                Next
            Next
        EndIf
    EndIf
    Return 1
EndFunc  ;==>_ArraySortClib

-_-------__--_-_-____---_-_--_-__-__-_ ^^€ñ†®øÞÿ ë×阮§ wï†høµ† ƒë@®, wï†høµ† †ïmë, @ñd wï†høµ† @ †ïmïdï†ÿ ƒø® !ïƒë. €×阮 ñø†, bµ† ïñ§†ë@d wï†hïñ, ñ@ÿ, †h®øµghøµ† †hë 맧ëñ§ë øƒ !ïƒë.

Share this post


Link to post
Share on other sites
myspacee

thank you for reply,

i want to explain to you my idea.

image that my number never go further than 10, so i based concept on find 'progressive' number:

___________________LOGIC

read first line and its number in file A
x = 1 

while

do until end of file A
   is FIRST number is = x ?

      if YES i found my first line write to file B and skip to find next number  (2) 

      if NO (number is <> 1)  read second line and SECOND  number

   is SECOND number is = 1 ?

      if YES i found my first line write to file B and skip to find next number  (3) 

      if NO (number is <> 1)  read second line and SECOND  number

end do

x = x + 1

wend

a bit complicated i know but few lines of code are needed

i'm stuck for bad programmer skill but in my mind this can work.

Sorry for english, and thank for help :)

m.

Share this post


Link to post
Share on other sites
PsaltyDS

thank you for reply,

i want to explain to you my idea.

image that my number never go further than 10, so i based concept on find 'progressive' number:

___________________LOGIC

read first line and its number in file A
x = 1 

while

do until end of file A
   is FIRST number is = x ?

      if YES i found my first line write to file B and skip to find next number  (2) 

      if NO (number is <> 1)  read second line and SECOND  number

   is SECOND number is = 1 ?

      if YES i found my first line write to file B and skip to find next number  (3) 

      if NO (number is <> 1)  read second line and SECOND  number

end do

x = x + 1

wend

a bit complicated i know but few lines of code are needed

i'm stuck for bad programmer skill but in my mind this can work.

Sorry for english, and thank for help :)

m.

If x and the size of A.txt is small then that might work in a reasonable amount of time. It would still be better to read A.txt into an array and loop through that in memory rather than reading the file over and over.

Try to code it in AutoIt, and if you get stuck post what you have so far to get more help.

:(


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
myspacee

Thank you all for reply, convinced that _ArraySortClib() method is best for my problem but,

i can adapt code for my text file, can anyone help me?

___________________ A.txt

PZ;C03POM;10;v;

PZ;PK5PNM;43;v;

PZ;P06PZM;52;b;

PZ;PZPPOM;1;b;

PZ;PT3PZM;44;b;

PZ;P05POM;9;b;

PZ;P02POM;2;v;

PZ;PS6POM;51;v;

PZ;P03POM;38;b;

PZ;PC1POM;15;b;

PZ;PC2POM;16;v;

PZ;PV6POM;37;v;

PZ;PZ4POM;28;b;

PZ;PZ2POM;25;b;

PZ;P07POM;26;v;

PZ;PZ3POM;27;v;

thank you again for your patiente,

m.

Share this post


Link to post
Share on other sites
Siao

Like this...

;1. Read file
$sData = FileRead("A.txt")

;2. Create 2D array, where $a2[$i][0] = value from selected column in Data, $a2[$i][1] = index (to refer to after sorting)
$a = _DSV_ColumnToArray($sData, 3, ";")
Dim $a2[UBound($a)][2]
For $i = 0 To UBound($a)-1
    $a2[$i][0] = $a[$i]
    $a2[$i][1] = $i+1 ;1-based index, to work with StringSplit later
Next

;3. Sort the array
_ArraySortClib($a2, 0)

;4. Make array of lines from Data
$aData = StringSplit(StringStripCR($sData), @LF)

;5. Write lines from array into new file, using index
$sData = $aData[$a2[0][1]]
For $i = 1 To UBound($a2)-1
    $sData &= @CRLF & $aData[$a2[$i][1]]
Next
FileWrite("A_Sorted.txt", $sData)


;   _DSV_ColumnToArray()
;   Extracts a column from delimiter separated values file to AutoIt array
Func _DSV_ColumnToArray(Byref $sData, $iColumn, $sDelim)
    Return StringRegExp($sData, "(?U)(?:\A|\n)(?:\V*" & $sDelim & "){" & $iColumn-1 & "}(\V*)(?:" & $sDelim & "|\v|\z)", 3)
EndFunc

"be smart, drink your wine"

Share this post


Link to post
Share on other sites
myspacee

thank you all and special kiss to Siao, works like a charm.

thank you

m.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×