Что нового

Разбить текстовый массив на 4 более-менее равных диапазона

ВиталийВВ

Новичок
Сообщения
177
Репутация
0
Добрый день!
Есть большой массив (одна строка - одно число, числа идут по нарастающей) типа:
1
2
3
4
5
6
7
8
9
10
(сумма = 55, четверть от нее = 13,75)
Надо этот диапазон разбить на 4 относительно (насколько это возможно с учетом округления) равных диапазона, и вывести типа 4 строки:
в данном случае это будет:
15 (сумма первых 5ти строк); 1-5 (первый/последний число этого диапазона); 5 (число строк)
21 (сумма след 3х строк, получается больше 13,75); 6-8(первый/последний число этого диапазона); 5 (число строк)
19 (сумма след 2х строк, получается больше 13,75); 9-10(первый/последний число этого диапазона); 2 (число строк)
И 4й диапазон (по аналогии делается, но тут он будет пустым)

1й диапазон сделал, дальше не могу сообразить.

Код:
$hFile = FileOpen(@ScriptDir & '\data.txt', 0)
$a1 = 0
$a2 = 0
$a3 = 0
$a4 = 0
$all = 10000000
$i1 = 0
$i2 = 0
$i3 = 0
$i4 = 0

; Проверяет, является ли файл открытым, перед тем как использовать функции чтения/записи в файл
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf

; Читает построчно текст, пока не будет достигнут конец файла EOF
While 1
    $sLine = FileReadLine($hFile)
    If @error = -1 Then ExitLoop
	;MsgBox (0, "0000", $sLine)

	If $a1 < $all/4 Then
    	$a1 = $a1+$sLine
		$i1 = $i1+1
		$sLine1 = $sLine
	EndIf

	If $a2 < $all/4 Then
    	$a2 = $a2+$sLine
		$i2 = $i2+1
		$sLine2 = $sLine
	EndIf



    ;If MsgBox(1, "Прочитанная строка:", $sLine) = 2 Then ExitLoop
WEnd

FileClose($hFile)

$s1 = $a1 & " т.руб.;" & "     " & $i1 & " сделок;" & "     " & "1 - " & $sLine1 & " размер сделки т.руб."
$s2 = $a2 & " т.руб.;" & "     " & $i2 & " сделок;" & "     " & "1 - " & $sLine2 & " размер сделки т.руб."

MsgBox(0, "Типа вот", $s1& @CRLF & $s2)

Сообщение автоматически объединено:

Вообще - написал, дотерзал, но получилось неизящно совсем :-(. Подскажите как более симпатично код сделать? В данном случае делится на 4 части, но хотелось бы более гибко подходить, а не городить, как тут вышло?:
Сообщение автоматически объединено:

Код:
$hFile = FileOpen(@ScriptDir & '\data.txt', 0)
$a1 = 0
$a2 = 0
$a3 = 0
$a4 = 0
$all = 10000000
$i1 = 0
$i2 = 0
$i3 = 0
$i4 = 0

$t1 = 0
$t2 = 0
$t3 = 0

$z = 0
$sLine2 = 0
$sLine3 = 0

$l = 0
$l2 = 0
$l3 = 0

FileDelete ("itog.txt")

; Проверяет, является ли файл открытым, перед тем как использовать функции чтения/записи в файл
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf

; Читает построчно текст, пока не будет достигнут конец файла EOF
While 1
    $sLine = FileReadLine($hFile)
    If @error = -1 Then ExitLoop
	;MsgBox (0, "0000", $sLine)

	If $a1 < $all/4 Then
    	$a1 = $a1+$sLine
		$i1 = $i1+1
		$sLine1 = $sLine
	EndIf
;---------------------------------------------------------
	If $t1 = 1 And $a2 < $all/4 Then
		MsgBox (0, "считаем 2", $sLine)
    	$a2 = $a2+$sLine
		$i2 = $i2+1
		If $l = 0 Then
			$l = 1
			$sLine2 = $sLine
		EndIf
		$sLine3 = $sLine
	EndIf

	If $a1 > $all/4 And $t1 = 0 Then
		$t1 = 1
		MsgBox (0, "22", $a1)
		$z = $sLine
	EndIf
	;------------------------------------------------------
	If $t2 = 1 And $a3 < $all/4 Then
		MsgBox (0, "считаем 3", $sLine)
    	$a3 = $a3+$sLine
		$i3 = $i3+1
		If $l2 = 0 Then
			$l2 = 1
			$sLine4 = $sLine
		EndIf
		$sLine5 = $sLine
	EndIf

	If $a2 > $all/4 And $t2 = 0 Then
		$t2 = 1
		MsgBox (0, "33", $a2)
		$z = $sLine
	EndIf
;-----------------------------------------------------------
	If $t3 = 1 And $a4 < $all/4 Then
		MsgBox (0, "считаем 4", $sLine)
    	$a4 = $a4+$sLine
		$i4 = $i4+1
		If $l3 = 0 Then
			$l3 = 1
			$sLine6 = $sLine
		EndIf
		$sLine7 = $sLine
	EndIf

	If $a3 > $all/4 And $t3 = 0 Then
		$t3 = 1
		MsgBox (0, "44", $a3)
		$z = $sLine
	EndIf


WEnd

FileClose($hFile)

$s1 = $a1 & " т.руб.;" & "     " & $i1 & " сделок;" & "     " & "1 - " & $sLine1 & " размер сделки т.руб."
$s2 = $a2 & " т.руб.;" & "     " & $i2 & " сделок;" & "     " & $sLine2 & " - " & $sLine3 & " размер сделки т.руб."
$s3 = $a3 & " т.руб.;" & "     " & $i3 & " сделок;" & "     " & $sLine4 & " - " & $sLine5 & " размер сделки т.руб."
$s4 = $a4 & " т.руб.;" & "     " & $i4 & " сделок;" & "     " & $sLine6 & " - " & $sLine7 & " размер сделки т.руб."

FileWriteLine ( "itog.txt", $s1& @CRLF&$s2& @CRLF&$s3& @CRLF&$s4)

MsgBox(0, "Типа вот", $s1 & @CRLF & $s2 & @CRLF & $s3 & @CRLF & $s4)
 
Последнее редактирование:

Oki

Продвинутый
Сообщения
452
Репутация
62
Подскажите как более симпатично код сделать?
Вместо однотипных имён с индексами использовать массивы, а по индексам этих массивов проходить в цикле. Все крайние случаи, чьё поведение не позволяет обработать их общей формулой, аккуратно отследить условными операторами для отдельной обработки.

Это, конечно, не готовый код, но дельные предложения по улучшению существующего.
 

Andrey_A

Продвинутый
Сообщения
325
Репутация
68
Приблизительный вариант, там много чего ещё можно повставлять: доп. проверки, условия...
Возможно пригодится.
Код:
#include <Array.au3>
$iM=4 ; на сколько частей разбивать
$aNum=StringSplit('1,2,3,4,5,6,7,8,9,10',',')
$iSum=_Sum_Num_Array($aNum)
$iMean=$iSum/$iM

$itmp=0
$sLine=''
For $i=1 To $aNum[0]
  $itmp+=$aNum[$i]
  If $itmp>$iMean Then
    $itmp=0
    $sLine&=$aNum[$i]&'|'
  Else
    $sLine&=$aNum[$i]&'+'
  EndIf
Next
If StringRight($sLine,1)='+'Then $sLine=StringTrimRight($sLine,1)
$aRes=StringSplit($sLine,'|')
_ArrayDisplay($aRes,'Массив $aRes')

; сумма чисел массива
; $aNum - массив (в первой ячейке количества элементов массива)
; $n = 1 , если целые числа в массиве идут последовательно
; $n = 0 , если числа в случайном порядке или с плавающей точкой
Func _Sum_Num_Array($aNum,$n=1)
  If $n Then Return($aNum[1]+$aNum[$aNum[0]])*($aNum[$aNum[0]]-$aNum[1]+1)/2
;   $n=0
  For $i=1 To $aNum[0]
    $n+=$aNum[$i]
  Next
  Return $n
EndFunc

Сообщение автоматически объединено:

Для файла
Код:
#include <Array.au3>
$iM=4 ; на сколько частей разбивать
$sFile='D:\data.txt'
$aNum=FileReadToArray($sFile)
$iSum=_Sum_Num_Array0($aNum)
$iMean=$iSum/$iM

$itmp=0
$sLine=''
For $i=0 To UBound($aNum)-1
  $itmp+=$aNum[$i]
  If $itmp>$iMean Then
    $itmp=0
    $sLine&=$aNum[$i]&'|'
  Else
    $sLine&=$aNum[$i]&'+'
  EndIf
Next
If StringRight($sLine,1)='+'Then $sLine=StringTrimRight($sLine,1)
$aRes=StringSplit($sLine,'|')
_ArrayDisplay($aRes,'Массив $aRes')

; сумма чисел массива
; $aNum - массив
; $n = 1 , если целые числа в массиве идут последовательно
; $n = 0 , если числа в случайном порядке или с плавающей точкой
Func _Sum_Num_Array0($aNum,$n=1)
  $iN=UBound($aNum)-1
  If $n Then Return($aNum[0]+$aNum[$iN])*($aNum[$iN]-$aNum[0]+1)/2
;   $n=0
  For $i=0 To $iN
    $n+=$aNum[$i]
  Next
  Return $n
EndFunc
 
Последнее редактирование:
Верх