# A question about transforming one List into two Lists with additional requirements

Background: I create geometric patterns by applying many linear transformations on geometries, I need functions to weed out the exponentially increasing number of ( unnecessary ) points involved which slow down the production of Graphics code.

The problem: Suppose I have the following array of arrays, for example two 2D vectors, a 2-by-2 matrix and one 3D vector in an array as follows: This format is not fixed however. ( Originates from reading data stored in Excel which can be 'dirty'. )

  { {1,2},{1,3}, {{1,0},{0,1}}, {10,20,30} } This format is invalid.
( Because it contains {10,20,30} , a 3D vector at the lowest level. )

{ {1,2},{1,3}, {{1,0},{0,1}}, {1,2} } This format is valid
( Because it contains only 2-D vectors at the lowest level, note the 2-by-2 matrix )


I want to replace the valid array with:

  { {1,2},{1,3},{1,0},{0,1} }
( a list of 2D vectors. )
{ 1, 2, {3,4}, 1 }
a list with the position of the row vectors in the list above.


Key part of the problem =>: Note that (1,2) is stored only once in the first list while it occurs twice in the original array. <=

Ideally I seek a validQ function that validates the input and a toGraph function that splits a valid row into two new rows. ( Although not a Graph Theory problem, there are similarities. I attempt to make the geometric pattern independent from its ( Cartesian ) coordinates. )

A complication is that the numbers are real ( square roots ) or involve Pi, and / or originate from spreadsheet calculations. Rounding or cutting to two places behind the decimal point is not a problem.

My attempts to solve this involved Map and Position, but my attempts failed, I can show no working snippet to start with. I hope that the example data suffices.

Question: Is there a clean functional style code to tackle this problem ?

• ndroock1, please consider cleaning up any outdated comments to the answers below. Apr 14 '12 at 18:02

Assuming valid data, I think this does what you need:

valid = {{1, 2}, {1, 3}, {{1, 0}, {0, 1}}, {1, 2}}

a={};
b=valid/.{x:List[_?NumericQ,_?NumericQ]:>(Position[a,x]/.{}:>{{Length[AppendTo[a,x]]}})[[1,1]]};
a
b

1. Regarding validation, you can replace every construct of type List[number,number] and see if there are other types of items remaining (after flattening). That should validate your input:

isValid[l_] := Length[DeleteCases[
Flatten[l /. List[_Real | _Integer, _Real | _Integer] :> Null /. List[] :> 0], Null]] == 0

2. Once you know the list is valid, you can recover your list of 2D vectors by flattening then partitioning:

Partition[Flatten[{{1, 2}, {1, 3}, {{{1, 0}}}, {0, 1}, {1, 2}}], 2]