Jump to content

Problems with array sorting correct lines and rearranging them and keep text below it for each.


wazer
 Share

Go to solution Solved by mikell,

Recommended Posts

This is how the original source would look like

#lib2
#txt-id="book78" txt-data="" txt-no="290" txt-logo="logo.jpg"
This is a text here belong to book78
#txt-id="book79" txt-data="" txt-no="100" txt-logo="logo.jpg"
This is a text here belong to book79
#txt-id="book80" txt-data="" txt-no="15" txt-logo="logo.jpg"
This is a text here belong to book80
#txt-id="book81" txt-data="" txt-no="250" txt-logo="logo.jpg"
This is a text here belong to book81
#txt-id="book82" txt-data="" txt-no="5" txt-logo="logo.jpg"
This is a text here belong to book82


This is the way the script current outputs it.

#lib2
#txt-id="book78" txt-data="" txt-no="10" txt-logo="logo.jpg"
#txt-id="book79" txt-data="" txt-no="9" txt-logo="logo.jpg"
#txt-id="book80" txt-data="" txt-no="8" txt-logo="logo.jpg"
#txt-id="book81" txt-data="" txt-no="7" txt-logo="logo.jpg"
#txt-id="book82" txt-data="" txt-no="6" txt-logo="logo.jpg"
This is a text here belong to book78
This is a text here belong to book79
This is a text here belong to book80
This is a text here belong to book81
This is a text here belong to book82

 

The dream scenario of how I would like it to output it as.

#Lib2
#txt-id="book82" txt-data="" txt-no="1" txt-logo="logo.jpg"
This is a text here belong to book82
#txt-id="book81" txt-data="" txt-no="2" txt-logo="logo.jpg"
This is a text here belong to book81
#txt-id="book80" txt-data="" txt-no="3" txt-logo="logo.jpg"
This is a text here belong to book80
#txt-id="book79" txt-data="" txt-no="4" txt-logo="logo.jpg"
This is a text here belong to book79
#txt-id="book78" txt-data="" txt-no="5" txt-logo="logo.jpg"
This is a text here belong to book78

 

I'm looking for some help to sort this out :=)

The very first line gets ignored
#Lib2

Then the next line is the lowest number found in txt-no="X" that gets converted from 1 and up, and then the text below it follows with it each #line

The script in current form.
 

#include <File.au3>
Dim $aFileArray, $aLength, $i

_FileReadToArray('source.txt', $aFileArray, 0)
_ArraySort($aFileArray)

$aLength = UBound($aFileArray)
For $i = 0 To $aLength - 1
  $aFileArray[$i] = StringRegExpReplace($aFileArray[$i],'(?<=txt-no=")[0-9]+(?=")', $aLength - $i)
Next
_FileWriteFromArray('output.txt',$aFileArray)

 

 

 

sort_script.au3 source.txt

Edited by wazer
Link to comment
Share on other sites

  • wazer changed the title to Problems with array sorting correct lines and rearranging them and keep text below it for each.

Not sure how long the text would get but maybe something like this will work:

#include <Array.au3>
#include <File.au3>
Dim $aFileArray, $aLength, $i
Local $sSource = FileRead("source.txt")
;~ Get sorted TextId list
Local $aTextId = StringRegExp($sSource, '(?:#txt-id=")(.*)(?:" txt-data=.*)', 3)
_ArraySort($aTextId, 1)

;~ Result array
Local $aLibrary[UBound($aTextId)+1][2]

Local $vSourceLine, $aSourceLine
;~ Split source text by @CRLF#
Local $aSourceList = StringSplit($sSource, @CRLF & "#", 3)
    If @error Then Exit MsgBox(4096, "Error", "Unable to split file")
;~ Loop through source list
For $i = 0 To UBound($aSourceList) - 1
    ;~ Split each line:
    ;~ Array[1] = #txd-id="
    ;~ Array[2] = book81
    ;~ Array[3] = " txt-data="" txt-no="
    ;~ Array[4] = 250
    ;~ Array[5] = " txt-logo.*
    ;~ Array[6] = This is a text here belong to book81
    $vSourceLine = StringRegExp("#" & $aSourceList[$i], '(#txt-id=")(.*)(" txt-data=.*txt-no=")(.*)(" txt-logo.*)(?:\R)(.*)', 4)
    ;~ Check for error code
    If Not @error Then
        ;~ Expand vSourceLine line item
        $aSourceLine = $vSourceLine[0]
        ;~ Get index of sorted $aTextId item and update Array[4] with new index number
        $aSourceLine[4] = _ArraySearch($aTextId, $aSourceLine[2]) + 1
        ;~ Add results to $aLibrary array
        $aLibrary[$aSourceLine[4]][0] = _ArrayToString($aSourceLine, "", 1, 5)
        $aLibrary[$aSourceLine[4]][1] = $aSourceLine[6]
    Else
        If $aSourceList[$i] = "#lib2" Then $aLibrary[0][0] = $aSourceList[$i]
    EndIf
Next
_ArrayDisplay($aLibrary)
ConsoleWrite(_ArrayToString($aLibrary, @CRLF, -1, -1, @CRLF) & @CRLF)

 

Link to comment
Share on other sites

Another way ...

#Include <Array.au3>

$txt = FileRead('source.txt')
$line1 = StringRegExp($txt, '^.+\R', 1)[0]
$r = StringRegExp($txt, '#txt.+\R.+', 3)
$n = UBound($r)
Local $res[$n][2]
For $i = 0 to $n-1
    $res[$i][0] = $r[$i]
    $res[$i][1] = StringRegExpReplace($r[$i], '(?s).*book(\d+).*', "$1")
Next
_ArraySort($res, 1, 0, 0, 1)
; _ArrayDisplay($res)

$txt = $line1 & _ArrayToString($res, "|", 0, $n-1, @crlf, 0, 0)
Msgbox(0,"", $txt)

 

Link to comment
Share on other sites

9 hours ago, Subz said:

Not sure how long the text would get but maybe something like this will work:

#include <Array.au3>
#include <File.au3>
Dim $aFileArray, $aLength, $i
Local $sSource = FileRead("source.txt")
;~ Get sorted TextId list
Local $aTextId = StringRegExp($sSource, '(?:#txt-id=")(.*)(?:" txt-data=.*)', 3)
_ArraySort($aTextId, 1)

;~ Result array
Local $aLibrary[UBound($aTextId)+1][2]

Local $vSourceLine, $aSourceLine
;~ Split source text by @CRLF#
Local $aSourceList = StringSplit($sSource, @CRLF & "#", 3)
    If @error Then Exit MsgBox(4096, "Error", "Unable to split file")
;~ Loop through source list
For $i = 0 To UBound($aSourceList) - 1
    ;~ Split each line:
    ;~ Array[1] = #txd-id="
    ;~ Array[2] = book81
    ;~ Array[3] = " txt-data="" txt-no="
    ;~ Array[4] = 250
    ;~ Array[5] = " txt-logo.*
    ;~ Array[6] = This is a text here belong to book81
    $vSourceLine = StringRegExp("#" & $aSourceList[$i], '(#txt-id=")(.*)(" txt-data=.*txt-no=")(.*)(" txt-logo.*)(?:\R)(.*)', 4)
    ;~ Check for error code
    If Not @error Then
        ;~ Expand vSourceLine line item
        $aSourceLine = $vSourceLine[0]
        ;~ Get index of sorted $aTextId item and update Array[4] with new index number
        $aSourceLine[4] = _ArraySearch($aTextId, $aSourceLine[2]) + 1
        ;~ Add results to $aLibrary array
        $aLibrary[$aSourceLine[4]][0] = _ArrayToString($aSourceLine, "", 1, 5)
        $aLibrary[$aSourceLine[4]][1] = $aSourceLine[6]
    Else
        If $aSourceList[$i] = "#lib2" Then $aLibrary[0][0] = $aSourceList[$i]
    EndIf
Next
_ArrayDisplay($aLibrary)
ConsoleWrite(_ArrayToString($aLibrary, @CRLF, -1, -1, @CRLF) & @CRLF)

 

This works really well, however when reading the original sources it will give error, the filenames would be SomethingName.book

So I uploaded one of the files with text in it and called it source.book, it will give the error Unable to split file

However If I create a txt file first then copy the content into the file and rename it source.book it works ?

source.book source_created_as_txt_file.book

Link to comment
Share on other sites

4 minutes ago, Subz said:

It's because it's trying to split on @CRLF, the source.book only uses @LF

Hope that makes sense.

Local $aSourceList = StringSplit($sSource, @LF & "#", 3)

 

WOOAH?

How can you tell that by reading 2 files being identical inside?

1 last thing I see there's a empty line after #lib2

ConsoleWrite outputs

#lib2

 

#txt-id="book82" txt-data="" txt-no="1" txt-logo="logo.jpg"

Link to comment
Share on other sites

Just now, mikell said:

Looks like you didn't even try my snippet - which btw works with source.book too
Doesn't matter :rolleyes:

I was about to test yours too, my head dont work so fast sorry :)

Let me play around with yours too and see what happens :)

Link to comment
Share on other sites

Ah sorry, I just modified 1 line :

#Include <Array.au3>

$txt = FileRead('source.book')
$line1 = StringRegExp($txt, '^.+\R', 1)[0]
$r = StringRegExp($txt, '#txt.+\R.+', 3)
$n = UBound($r)
Local $res[$n][2]
For $i = 0 to $n-1
    $res[$i][0] = StringRegExpReplace($r[$i],'.*txt-no="\K(\d+)', $n-$i)
    $res[$i][1] = StringRegExpReplace($r[$i], '(?s).*book(\d+).*', "$1")
Next
_ArraySort($res, 1, 0, 0, 1)
; _ArrayDisplay($res)

$txt = $line1 & _ArrayToString($res, "|", 0, $n-1, @crlf, 0, 0)
Msgbox(0,"", $txt)

 

Link to comment
Share on other sites

19 minutes ago, mikell said:

Ah sorry, I just modified 1 line :

#Include <Array.au3>

$txt = FileRead('source.book')
$line1 = StringRegExp($txt, '^.+\R', 1)[0]
$r = StringRegExp($txt, '#txt.+\R.+', 3)
$n = UBound($r)
Local $res[$n][2]
For $i = 0 to $n-1
    $res[$i][0] = StringRegExpReplace($r[$i],'.*txt-no="\K(\d+)', $n-$i)
    $res[$i][1] = StringRegExpReplace($r[$i], '(?s).*book(\d+).*', "$1")
Next
_ArraySort($res, 1, 0, 0, 1)
; _ArrayDisplay($res)

$txt = $line1 & _ArrayToString($res, "|", 0, $n-1, @crlf, 0, 0)
Msgbox(0,"", $txt)

 

This works really well as well!

And as always I made an error!!!!, the actually output needs to be find the lowest number in txt-no, then put it as the first write order.

Source

#lib2
#txt-id="book78" txt-data="" txt-no="290" txt-logo="logo.jpg"
This is a text here belong to book78
#txt-id="book79" txt-data="" txt-no="100" txt-logo="logo.jpg"
This is a text here belong to book79
#txt-id="book80" txt-data="" txt-no="15" txt-logo="logo.jpg"
This is a text here belong to book80
#txt-id="book81" txt-data="" txt-no="250" txt-logo="logo.jpg"
This is a text here belong to book81
#txt-id="book82" txt-data="" txt-no="5" txt-logo="logo.jpg"
This is a text here belong to book82


Rotates to this
 

#lib2
#txt-id="book82" txt-data="" txt-no="5" txt-logo="logo.jpg"
This is a text here belong to book82
#txt-id="book80" txt-data="" txt-no="15" txt-logo="logo.jpg"
This is a text here belong to book80
#txt-id="book79" txt-data="" txt-no="100" txt-logo="logo.jpg"
This is a text here belong to book79
#txt-id="book81" txt-data="" txt-no="250" txt-logo="logo.jpg"
This is a text here belong to book81
#txt-id="book78" txt-data="" txt-no="290" txt-logo="logo.jpg"
This is a text here belong to book78


And final ouput would be this.

#lib2
#txt-id="book82" txt-data="" txt-no="1" txt-logo="logo.jpg"
This is a text here belong to book82
#txt-id="book80" txt-data="" txt-no="2" txt-logo="logo.jpg"
This is a text here belong to book80
#txt-id="book79" txt-data="" txt-no="3" txt-logo="logo.jpg"
This is a text here belong to book79
#txt-id="book81" txt-data="" txt-no="4" txt-logo="logo.jpg"
This is a text here belong to book81
#txt-id="book78" txt-data="" txt-no="5" txt-logo="logo.jpg"
This is a text here belong to book78

 

Also having a first decider number would be cool and will fix a lot more problems.

Let say the library starts from 1 and up to 100, then when I convert the next shelf i could put in starting number 101 instead of 1 to make sure they play a long?

Edited by wazer
Link to comment
Share on other sites

OK next try :D

BTW I don't undestand cleary what you mean with "decider number"

#Include <Array.au3>

$txt = FileRead('source.book')
$line1 = StringRegExp($txt, '^.+\R', 1)[0]
$r = StringRegExp($txt, '#txt.+\R.+', 3)
$n = UBound($r)
Local $res[$n][2]
; step #1

For $i = 0 to $n-1
    $res[$i][0] = $r[$i]
    $res[$i][1] = Execute('"' & StringRegExpReplace($r[$i], '(?s).*txt-no="(\d+).*', '" & StringFormat("%03i", "$1") & "') & '"')
Next
_ArraySort($res, 0, 0, 0, 1)
 _ArrayDisplay($res)

; step #2
For $i = 0 to $n-1
    $res[$i][0] = StringRegExpReplace($res[$i][0],'.*txt-no="\K(\d+)', $i+1)
Next

$txt = $line1 & _ArrayToString($res, "", 0, $n-1, @crlf, 0, 0)
Msgbox(0,"", $txt)

 

Link to comment
Share on other sites

13 minutes ago, mikell said:

OK next try :D

BTW I don't undestand cleary what you mean with "decider number"

#Include <Array.au3>

$txt = FileRead('source.book')
$line1 = StringRegExp($txt, '^.+\R', 1)[0]
$r = StringRegExp($txt, '#txt.+\R.+', 3)
$n = UBound($r)
Local $res[$n][2]
; step #1

For $i = 0 to $n-1
    $res[$i][0] = $r[$i]
    $res[$i][1] = Execute('"' & StringRegExpReplace($r[$i], '(?s).*txt-no="(\d+).*', '" & StringFormat("%03i", "$1") & "') & '"')
Next
_ArraySort($res, 0, 0, 0, 1)
 _ArrayDisplay($res)

; step #2
For $i = 0 to $n-1
    $res[$i][0] = StringRegExpReplace($res[$i][0],'.*txt-no="\K(\d+)', $i+1)
Next

$txt = $line1 & _ArrayToString($res, "", 0, $n-1, @crlf, 0, 0)
Msgbox(0,"", $txt)

 

This looks outstanding and did a small random test the orders seems to be correct now :D


For the decider thing


I would have multiple source.book files over time

Current we say find lowest numbers and sort them from lowest to highest, then we give lowest numbers 1 and up.

then when I add the next file it would start from 1 again, I would like to manually assign the number it should start from, lets say 101 instead of 1, over time when we get all books scanned in I could assign the next number in the line when merging them all into 1 big file.

Edited by wazer
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...