2
$\begingroup$

Say I have a list:

{{Line[{{-Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}}], 
Line[{{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0,1}}]}, 
{Line[{{-Sqrt[5/8 + Sqrt[5]/8],1/4 (-1 + Sqrt[5])}, {Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}}], 
Line[{{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}}]}}

So that each sublist of that list consist of, in this case, two lines. All the points that tell us about the position of the line appear in another list, call this list points. Now, I want to extract the position of all the points from the above list in that points list. I'm aware of Position function but I'm not sure how to effectively apply it to my big list above in order to get the list of positions. AI'd very much appreciate some help.

$\endgroup$
1

5 Answers 5

4
$\begingroup$

You can use Cases for this:

lines = {{Line[{{-Sqrt[5/8 - Sqrt[5]/8], 
       1/4 (-1 - Sqrt[5])}, {0, 1}}], 
    Line[{{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 
       1}}]}, {Line[{{-Sqrt[5/8 + Sqrt[5]/8], 
       1/4 (-1 + Sqrt[5])}, {Sqrt[5/8 - Sqrt[5]/8], 
       1/4 (-1 - Sqrt[5])}}], 
    Line[{{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}}]}};

Catenate @ Cases[lines, Line[pts : {{_, _} ..}] :> pts, Infinity]

Out[5]= {{-Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}, {Sqrt[ 5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}, {-Sqrt[5/8 + Sqrt[5]/8], 1/4 (-1 + Sqrt[5])}, {Sqrt[ 5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}}

$\endgroup$
1
  • $\begingroup$ Thank you @SjoerdSmit! Tbh, for my case, it makes more sense to not Catenate them and keep them within the sublists as initially. When I remove Catenate it gives a list of lists of points representing each line, as expected. But then it again looses the sublist's structure. $\endgroup$
    – amator2357
    Commented Feb 14, 2019 at 12:21
4
$\begingroup$

What about /.Line->List

lines /. Line -> (Flatten[ List[#], 1] &)
$\endgroup$
1
  • 2
    $\begingroup$ +1. Or perhaps even lines /. Line -> Sequence. $\endgroup$
    – WReach
    Commented Feb 14, 2019 at 15:20
2
$\begingroup$

Answer to what you want

lines = {
    { Line[{{-Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0,1}}]
    , Line[{{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0,1}}]
    }
    , { Line[{{-Sqrt[5/8 + Sqrt[5]/8], 1/4 (-1 + Sqrt[5])}, {Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}}]
    , Line[{{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}, {0, 1}}]
    }
};    

lines /. Line[ l : { {_, _} ..} ] :> l

(* or as WReach has pointed out:  lines /. Line -> Sequence *)

Simple and expressive - no remembering whether its Flatten[ ... , 1 ] or Flatten[ ... , {1} ], or Flatten[ ... , -1 ] and what have you.

Different Approach Making Use of Datatypes

While having lists is very compact we can easily get lost in different levels. Why not simply give each single point the head Point (Point can also contain a list of {x,y} tuples like Line, but giving each point a head of its own simplifies counting and identification of duplicates imo). You can then use pattern matching quite easily, count points, and immediately visualize the data:

Here I turn a list of lines into a list of points, thus not adding another level for each line:

points = lines /. Line[ l : { { _, _ }.. } ] :> ( Sequence @@ Point /@ l )

(* if you do not want this you can simply do: lines /. Line -> Point *)

{{Point[{-Sqrt[5/8-Sqrt[5]/8],1/4 (-1-Sqrt[5])}],Point[{0,1}],Point[{Sqrt[5/8-Sqrt[5]/8],1/4 (-1-Sqrt[5])}],Point[{0,1}]},{Point[{-Sqrt[5/8+Sqrt[5]/8],1/4 (-1+Sqrt[5])}],Point[{Sqrt[5/8-Sqrt[5]/8],1/4 (-1-Sqrt[5])}],Point[{Sqrt[5/8-Sqrt[5]/8],1/4 (-1-Sqrt[5])}],Point[{0,1}]}}

Now it is easy to count points:

Count[ points, Point[ _ ], Infinity ]

8

It is easy to discover that there are only four unique points:

Flatten @ points // Union

{Point[{0, 1}], Point[{-Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}], Point[{Sqrt[5/8 - Sqrt[5]/8], 1/4 (-1 - Sqrt[5])}], Point[{-Sqrt[5/8 + Sqrt[5]/8], 1/4 (-1 + Sqrt[5])}]}

And we can immediately visualize the results:

Graphics[ {Red, PointSize -> Large, points} ]

Plot of Points

Don't care for Point anymore? Get back to lists:

points /. Point[ pos : { _, _ } ] :> pos
$\endgroup$
2
$\begingroup$

To make things easier to read, let's use these lines (with the same nested structure as in the question):

lines =
  { { Line[{{60, 50}, {60, 70}}]
    , Line[{{40, 30}, {40, 50}}]
    }
  , { Line[{{20, 10}, {20, 30}}]
    }
  };

Furthermore, let's define the list points as this:

points = {{20, 10}, {20, 30}, {40, 30}, {40, 50}, {60, 50}, {60, 70}};

We can get the positions of each point in this list as follows:

pointPosition = points // PositionIndex // Map[First]

(* <|{20, 10} -> 1, {20, 30} -> 2, {40, 30} -> 3, {40, 50} -> 4, {60, 50} -> 5, {60, 70} -> 6|> *)

This association can tell us, for example, that the point {40, 30} appears at position 3 in points.

pointPosition[{40, 30}]

(* 3 *)

We can now convert the line list into a similarly structured list where each point has been replaced by a pair of corresponding positions:

lines /. Line[pts__] :> pointPosition /@ pts

(* {{{5, 6}, {3, 4}}, {{1, 2}}} *)

Or, should we desire, we could retain the List heads in the result:

lines /. Line[pts__] :> Line[pointPosition /@ pts]

(* {{Line[{5, 6}], Line[{3, 4}]}, {Line[{1, 2}]}} *)

This latter form has the advantage that we can still draw the resultant lines by means of GraphicsComplex:

newLines = lines /. Line[pts__] :> Line[pointPosition /@ pts];

Graphics[GraphicsComplex[points, newLines]]

line graphics

$\endgroup$
1
$\begingroup$

As bad as it may look, this seems to be working fine:

Partition[Partition[Flatten[Position[points, #] & /@ Catenate @ Cases[lines, Line[pts : {{_, _} ..}] :> pts, Infinity]],2],Length[l]]

$\endgroup$
1
  • $\begingroup$ Working code is one thing - readable and debuggable code another (try understanding that code three months from now). I tend to go for the union of these. :) $\endgroup$
    – gwr
    Commented Feb 14, 2019 at 14:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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