Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

complicated array sorting

Status
Not open for further replies.

m4trix

Vendor
Jul 31, 2002
84
CA
This isn't as hard as I think it is - but I'm just not thinking right at the moment.

Ok, I'm having trouble describing what I need. so I'll give you an example. Sorry if it's hard to understand.

say I have an array of numbers:

(15,5,25,10,20)

the percentage of each number can be represented in an array by dividing each element by the sum of all of them (75):

(0.2, 0.0667, 0.333, 0.133, 0.267)

now, I have a second arbitrary value (let's say 20) that needs to be multiplied by one of these percentages, and added to the original element, such that the highest numbers are added to 20 * the lowest percentage.. but the orignal array must remain in order.

if the original array and percentage array were ordered, they'd become:
(5, 10, 15, 20, 25) and (0.0667, 0.133, 0.2, 0.267, 0.333)
so in THIS order, we get:
5 + (20 * 0.333) = 11.66
10 + (20 * 0.267) = 15.34
15 + (20 * 0.2) = 19
20 + (20 * 0.133) = 22.66
25 + (20 * 0.0667) = 26.334

but it needs to be in the same order as the original array:
Such that the original array:
(15,5,25,10,20)

becomes:
(19, 11.66, 26.334, 15.34, 22.66)


The only way I can think of doing this is to sort the array manually, so that you can sort a second array at the same time containing index values. Then multiply each by the inverse percentage, then "unsort" the array again using the array of indexes that was sorted at the beginning. I'm wondering if there's an easier way though. I hate writing manual sort algorithms.
 
This isn't that hard. All you need to do is create a second array that mirrors the first array. If you don't reorder things, it will remain in the same order:

Lets call your initial array arrOrig and the second array arrCalc. The first step is to build the second array and calculate the total in order to make the averages later on:

Code:
$arrOrig = array(15,5,25,10,20);
	$intTotal = 0;
	for ($i=0; $i<sizeof($arrOrig); $i++)
	{
		$intTotal += $arrOrig[$i];
		$arrCalc[] = $arrOrig[$i];
	}

The second step is to do the calculations for the values in the second array:

Code:
for ($i=0; $i<sizeof($arrCalc); $i++)
	{
		$arrCalc[$i] = ($arrCalc[$i] / $intTotal) * 20;
	}

That should do the trick. You'll notice the resulting values differ from your example because your math wasn't correct (20 * 0.2 = 4 not 19).

Good luck :)

Take Care,
Mike
 
I think my explanation confused you, or you left something out. Thanks for the try though.

I ended up figuring out one way of doing it. It may not be terribly efficient, but it will serve for my purposes. I'll post it in case anyone is curious. Regarding the naming scheme - the purpose of this is to create a table in a pdf document. The table width is static, but the col width depends on the # of colums and the header within them. The header is centered, so extra space is &quot;padded&quot; on each column. Wide headers would appear too wide and narrow ones too narrow if the spacing was the same for all, so I wrote this to &quot;smooth&quot; the column widths out.

info you need to know:
$courses = array of column header strings
$course_s = array of (physical) string lengths
table width is fixed at 225.5 mm.

so:
Code:
$course_s = $indexes = array();
$asize = count($courses);
for($i=0;$i<$asize;$i++){
	$size += $pdf->GetStringWidth($courses[$i]);       // fpdf class func
	$course_s[$i] = $pdf->GetStringWidth($courses[$i]);
	array_push($indexes,$i);
}
$padd = 225.5 - $size;
insertionSort(&$course_s,$asize,&$indexes);  // sorts course_s and indexes together (based on course_s)
for($i=0;$i<$asize;$i++){
    $padding[$indexes[$i]] = $course_s[($asize-1-$i)] / $size * $padd;
}


So if the width of each header ($course_s) is:
(30.46, 8.94, 12.94, 13.17, 5.64, 14.82, 32.57, 17.64)

the padding for each field is:
(5.86, 19.98, 11.57, 9.72, 21.36, 8.64, 3.70, 8.49)

and so the total width for each column:
(36.32, 28.92, 24.51, 22.89, 27.00, 23.46, 36.27, 26.13)

which adds up to 225.5
 
P.S. If anyone can think of a better way of writing that

OR MORE IMPORTANTLY, a better &quot;smoothing&quot; algorithm, please post it, even if it's just an idea.

As it is, that works well, but it has flaws. For example, if there is an even number of columns, the middle column (widthwise) will always be multiplied by itself.

or say the widths are:
(5, 10, 20, 20, 20, 30)

then it becomes

5 x (30 as a percentage of total)
10 x (20...
20 x (20...
20 x (20...
20 x (10...
30 x (5...

as you can see, there are three identical column widths, but one of them will end up being narrower than the other two. It's things like that that I want to work out
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top