rkk has asked for the wisdom of the Perl Monks concerning the following question:
Hello,
I have a file like the following
ID1 ch1 70 mir abc xyz ch2 2050
ID2 ch1 90 mir abc xyz ch2 4000
ID3 ch1 100 mir abc xyz ch2 2045
ID4 ch1 120 mir abc xyz ch2 2025
I need to sort the last column and after sorting if the difference between first and last element is >=500 (in this example second line) that should be omitted and remaining three lines should be printed.
Output should be:
ID1 ch1 70 mir abc xyz ch2 2050
ID3 ch1 100 mir abc xyz ch2 2045
ID4 ch1 120 mir abc xyz ch2 2025
Any help in this task will be appreciated.
Thanks in advance,
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Array reference
by roboticus (Chancellor) on Jun 12, 2013 at 23:53 UTC | |
rkk: OK, let's do a little debugging. First, I took your script and added "use warnings" at the top, closed a couple curly braces, and added "my" before the @s_array. That was enough to make it compile cleanly. When I run it, my screen fills with:
It doesn't stop, so there's apparently an infinite loop. Well, let's run it under the debugger and see what the program is doing:
The 'n' command tells it to execute the next instruction. After that, pressing the Enter key repeats the command, so here we've just executed lines 4 through 9 and are ready to execute line 10. The debugging session continues... Before we run the next line, let's take a quick peek at what's in the @lines variable: Read more... (7 kB)
OK, now that I've done my bit, here's an observation on your code: It seems like you're trying to use @arr1, @arr2 and @arr3 to contain data that's logically tied together. If so, it would probably benefit you to get used to using an array of arrays, so each slot always has the related values you want. In other words, you can turn this:
Into this:
That way, if you need to interchange two rows in your arrays, instead of this:
you can do this:
This way, you're swapping around an array of related items, without a bunch of copypasta. Note: I didn't write the swaps in the best way, I did it as a beginner might. But in fact perl lets you assign a list to a list of values, so it's even easier to do it like this:
Well, I hope you find my rambling useful in some way. Let me know if you get stuck again. Update: Added a missing code tag, moved one sentence ("the debugging continues" moved up a line), added another sentence for clarity ("Now that we can see line 21"). ...roboticus When your only tool is a hammer, all problems look like your thumb. | [reply] [d/l] [select] |
|
Re: Array reference
by kcott (Archbishop) on Jun 13, 2013 at 00:18 UTC | |
G'day rkk, Welcome to the monastery. You seem to have got off on the wrong foot somewhat. Here's a few tips: Here's the guts of the code I might have used to tackle this problem:
After excluding the ID2 line, your data was already sorted. I've changed the order of the lines under __DATA__ to show that the sort works. Here's the output:
Update: I left the 500 out of the comparison. Fixed: s/$_->[-1] <= $first/$_->[-1] - $first <= 500/ -- Ken | [reply] [d/l] [select] |
by rkk (Novice) on Jun 13, 2013 at 15:10 UTC | |
Thanks all for the suggestions.. | [reply] |
|
Re: Array reference
by hbm (Hermit) on Jun 12, 2013 at 23:55 UTC | |
Classic map-sort-map: The only trick is, in #1, keep track of the smallest last column.
| [reply] [d/l] |
|
Re: Array reference
by GrandFather (Saint) on Jun 13, 2013 at 00:15 UTC | |
If I understand your requirements correctly the following sample should do it for you:
Prints:
The trick is to pair the line text with the sort key (done in the map) then subsequently use the key or the original line as required.
True laziness is hard work
| [reply] [d/l] [select] |
|
Re: Array reference
by LanX (Saint) on Jun 12, 2013 at 22:37 UTC | |
> Asking for help is one thing, but requesting us to just do your work for you for free is not going to happen - you should ask the kind folks at the perlguru's I need a program that... forum instead.
Cheers Rolf ( addicted to the Perl Programming Language) ¹) for those getting locked out, sorry! Deep linking [id://172086#your_work] didn't work! And this is to general. ²) corrected link, thx ano-monk for link to workaround | [reply] |
by rkk (Novice) on Jun 12, 2013 at 22:55 UTC | |
well.. I also know that no body wants to write a code for free.. I have asked for the help not for the entire code..
Thanks. | [reply] [d/l] |
by JockoHelios (Scribe) on Jun 12, 2013 at 23:31 UTC | |
From the input and desired output you posted, it appears that you want to sort on the last field in each array, then remove any row based on the difference in that last field. Is that correct ? First, my @s_arr2 must be declared for this line@s_arr2=sort{$a<=>$b}@arr2; Then, on this lineif(abs($l2[3]-$l1[3]) <= 500 && $l1[6] eq $l2[6]) are you intending to subtract text fields in the abs section ? Based on your data, you're subtracting "mir" from "mir" because Perl array indices start with zero.Also on that same line, if you meant abs($l2[2]-$l1[2]) <= 500to do subtractions on the 70, 90, 100, 120 values, those differences won't come close to 500, so no row would be deleted based on that result.
Dyslexics Untie !!!
| [reply] [d/l] [select] |
by Anonymous Monk on Jun 13, 2013 at 00:24 UTC | |
) for those getting locked out, sorry! Having Writeups: 2622 means you should not be sorry :) Markup in the Monastery, Shortcut for Linking by Numeric Node ID [id://nodeid] should accept #anchors | [reply] |
|
Re: Array reference
by JockoHelios (Scribe) on Jun 12, 2013 at 22:34 UTC | |
Please post your script. If you don't have one, don't expect someone to just write one for you. There are sites where you can hire someone to write Perl script to your specifications. But you have to pay them.
Dyslexics Untie !!!
| [reply] |
by rkk (Novice) on Jun 12, 2013 at 22:52 UTC | |
well.. I also know that no body wants to write a code for free.. I have asked for the help not for the entire code..
Thanks. | [reply] [d/l] |