Jump to content

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


Go to solution Solved by mikell,

Recommended Posts

Posted (edited)

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
  • wazer changed the title to Problems with array sorting correct lines and rearranging them and keep text below it for each.
Posted

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)

 

Posted

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)

 

Posted
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

Posted
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"

Posted
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 :)

Posted

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)

 

Posted (edited)
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
Posted

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)

 

Posted (edited)
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
  • Solution
Posted

Hmmm I understand - maybe ;)

If you want to do it manually, then you can simply use a variable
To test, in my previous code replace the step #2 by this one

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

 

Posted
2 minutes ago, mikell said:

Hmmm I understand - maybe ;)

If you want to do it manually, then you can simply use a variable
To test, in my previous code replace the step #2 by this one

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

 

Exactly this!

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
  • Recently Browsing   0 members

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