Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I import a data file:

SetDirectory["C:\\Users\\SE7EN\\Desktop\\mathematica\\test"];
dd = Import["data.dat", "Table"]

Out[2] = {{1}, {2}, {3}, {4}, {5}, {6}, {7}}

and I want to apply the statement below on the elements of the data file but it doesn't work

For[i = 1, i < 7, 
  i++, {If[dd[[i]] < dd[[i + 1]], Print[dd[[i + 1]]], 
    If[i > 5, Print[dd[[i]]]]]}];

Of course there are some other ways to the goal of the program but I want to work with the elements of an imported data file directly in the first of IF statement.

share|improve this question
1  
Because the data is a list of (single element) lists, and your comparison is on those lists - meaningless. Either Flatten dd, or use dd[[i,1]] to specify the first (and only) element. Also, the i>5 part of your compound If will never be reached with your example data... –  rasher May 22 at 3:04
    
Thank you so much. You removed my problem. All the Best –  mostafa May 22 at 4:10
    
To the close voter: no problems if the community does want to close, but I would argue that non-comparability of single-element lists using Greater and Less etc is not easily found in the documentation. –  Verbeia May 22 at 4:46
    
@Verbeia: Somewhat agree docs. are a bit opaque about this, based on your detailed almost tutorial answer, voted to keep open, and +1 on answer you took the time to craft. –  rasher May 22 at 6:14
    
@rasher - thanks - I specialise in that kind of answer to this kind of question. :) –  Verbeia May 22 at 7:18
add comment

1 Answer 1

up vote 5 down vote accepted

rasher is totally correct in his comment. The reason why you aren't getting any result is that you are not actually comparing things that can be compared. You can see this with the following.

Table[dd[[i]] < dd[[i + 1]], {i, 6}]
(* {{1} < {2}, {2} < {3}, {3} < {4}, {4} < {5}, {5} < {6}, {6} < {7}}*)

The smallest fix is to Flatten your data before putting it in the loop, as rasher suggested.

With[{ddd = Flatten[dd]}, 
  For[i = 1, i < 7,  i++, {If[ddd[[i]] < ddd[[i + 1]], Print[ddd[[i + 1]]], 
     If[i > 5, Print[ddd[[i]]]]]}]];

But honestly, this sort of For loop is a very inefficient and hard to read approach. There are many more "Mathematica-like" ways to do this: see here and here. Also you need to care what the length of the data are in order to construct your loop, for example by changing the 7 above to Length[dd]. Here is an alternative:

Last /@ Select[Join[Most[dd], Rest[dd], 2], Less @@ ## &]

To explain what this is doing, I'm just creating a larger data set that puts the ith and i+1th part of dd together on a single row, Selecting only the rows where the first element is less than the second, and then keeping the last element of that row, which will be the i+1th element of the original list. If you aren't sure about the ##, it means SlotSequence.

Of course, this doesn't handle that second If statement, but as rasher pointed out, it will never be reached with the data you have provided.

Here's another example if the i>5 test doesn't actually matter. In this case I've left the curly braces around each element of the result. Notice the use of the Part specification ([[1]]) in the If condition, to ensure that you actually have numbers that can be compared, not single-element lists, that can't be. Alternatively you could Flatten the original data dd. Either way works just fine.

MapThread[If[#2[[1]] > #1[[1]], #2, #1] &, {Most[dd], Rest[dd]}]
(* {{2}, {3}, {4}, {5}, {6}, {7}} *)

Here is an example using MapIndexed that does deal with that second If statement. To test it, I'm going to use some different data.

ddr = Transpose[{RandomInteger[{1, 10}, 12]}]
(* {{7}, {1}, {5}, {5}, {9}, {9}, {9}, {4}, {7}, {7}, {5}, {9}} *)

Notice how I've used a replacement rule (Null->Sequence[]) at the end to delete the cases where dd[[i]] >= dd[[i+1]], but i<=5. Your code didn't allow for that case. It is important to allow for such exhaustive cases, unless you are very sure of the structure and values of your data.

MapIndexed[
  If[Less @@ #1, Last[#1], If[First[#2] > 5, First[#1], Null]] &, 
  Join[Most[ddr], Rest[ddr], 2]] /. Null -> Sequence[]
(* {5, 9, 9, 9, 7, 7, 7, 9} *)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.