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.

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 ?

share|improve this question
    
ndroock1, please consider cleaning up any outdated comments to the answers below. –  Mr.Wizard Apr 14 '12 at 18:02
add comment

2 Answers

up vote 3 down vote accepted

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
share|improve this answer
add comment
  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]
    
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.