# List manipulation by indices of indexed variable names [closed]

Each of my indexed variable represents a curve, and each variable has four indices with practical meaning, e.g. first index indicates whether this curve is a bedding interface(1) or fault (2).; second index indicates the upper lithology, third index indicates underlying lithology and fourth indicates serials number of multiple sections of the interface. I want to do some manipulation with these curves. Currently I achieve this by converting name indices to numerical lists and converting between string and expression, which is too clumsy. My problem is, could you work directly on the indices in the variable name to achieve these goals? Thanks.

Alternatively the indices can be expressed as sublists like: hf[[1]]={{1,1,2,1},{{x1,y1},{x2,y2},...,{xn,yn}}, then I can do the list manipulation based on the elements of the sublist.

My goal is to efficiently manage the interfaces representing a 2-D underground model (shown after the code), and associate the interfaces with its up and low lithology (different colors).

Clear[hf]

hf[1,1,2,1]={{30,-40},{60,-50}};
hf[1,4,5,1]={{30,-50},{60,-60}};
hf[1,4,5,2]={{70,-45},{90,-40}};
hf[1,5,6,1]={{30,-65},{60,-78}};
hf[2,4,6,1]={{60,-78},{65,-40}};

allCurve = {hf[1, 1, 2, 1], hf[1, 4, 5, 1],
hf[1, 4, 5, 2], hf[1, 5, 6, 2], hf[2, 4, 6, 1]};
curveIndexList = {{1, 1, 2, 1}, {1, 4, 5, 1}, {1, 4, 5, 2}, {1, 5, 6,
1}, {2, 4, 6, 1}};

(*Collect all the curves around lithology unit 4 (either the second or the third index equals to 4*)
poly4IndexList = Cases[curveIndexList, {x1_, x2_, x3_, x4_} /; x2 == 4 || x3 == 4];

poly4 = ToExpression@Table[StringReplace["hf" <> ToString[poly4IndexList[[i]]], {"{" -> "[", "}" -> "]"}], {i, 1, Length@poly4IndexList}]

(*So there are 3 curves selected and they form a joined list:*)
[out]= {{{30, -50}, {60, -60}}, {{70, -45}, {90, -40}}, {{60, -78}, {65, -40}}}


-
You should be aware that many Mathematica list manipulation operations also work on expressions with any head. –  m_goldberg Jul 5 '13 at 13:46
If you are using indices, shouldn't you be using double brackets? hf[[]]? –  bobthechemist Jul 5 '13 at 13:52
It seems you want Apply the function List at the first level, i.e. List @@@ allCurve. –  Artes Jul 5 '13 at 14:05
Wow... 18 revisions for a question asked yesterday?! Please do not repeatedly edit and bump your question or carry out conversations in questions. Rather, think through your question well either before asking or updating it in an edit. –  rm -rf Jul 6 '13 at 19:10
Thank you very much for reposting my question, Verbeia. You are a nice guy. God bless you! –  yanfyon Jul 8 '13 at 2:55

## closed as unclear what you're asking by m_goldberg, Artes, Yves Klett, bill s, rm -rf♦Jul 6 '13 at 19:12

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question.If this question can be reworded to fit the rules in the help center, please edit the question.

I think the function(s) you need to look up are Thread, Apply, Position and Extract.

It seems you have a set of what you call indices:

curveIndexList = {{1, 1, 2, 1}, {1, 2, 3, 1}, {2, 2, 3, 1}, {2, 2, 4,
1}, {1, 3, 4, 1}, {1, 3, 4, 2}, {2, 3, 4, 1}, {1, 4, 5, 1}, {1, 4,
5, 2}, {2, 3, 5, 1}, {2, 4, 5, 1}, {2, 4, 6, 1}, {1, 5, 6,
1}, {1, 5, 6, 2}, {1, 5, 6, 3}, {2, 5, 11, 1}, {2, 5, 6, 1}, {1,
6, 11, 1}, {1, 6, 11, 2}, {1, 6, 11, 3}, {2, 6, 11, 1}, {2, 6, 13,
1}, {1, 11, 13, 1}, {1, 11, 13, 2}, {1, 11, 13, 3}, {2, 11, 13,
1}, {1, 13, 8, 1}, {1, 13, 12, 1}, {1, 13, 8, 2}, {1, 8, 9,
1}, {1, 6, 7, 1}, {1, 6, 7, 2}, {1, 7, 6, 1}, {1, 7, 11, 1}, {1,
7, 11, 2}};


but I think you mean them to be function arguments, passed on to a function hf. Each of those corresponds to "something" (list, number, string etc):

    somethings = {something1, something2, something3, something4, something5,
something6, something7, something8, something9, something10,
something11, something12, something13, something14, something15,
something16, something17, something18, something19, something20,
something21, something22, something23, something24, something25,
something26, something27, something28, something29, something30,
something31, something32, something33, something34, something35}


First of all, if you want to apply your function to curveIndexList at the first level (i.e. this being a list of lists, you want a list of functions), you can do it like so:

funcs = Apply[hf, curveIndexList, {1}]

(*{hf[1, 1, 2, 1], hf[1, 2, 3, 1], hf[2, 2, 3, 1], hf[2, 2, 4, 1],
hf[1, 3, 4, 1], hf[1, 3, 4, 2], hf[2, 3, 4, 1], hf[1, 4, 5, 1],
hf[1, 4, 5, 2], hf[2, 3, 5, 1], hf[2, 4, 5, 1], hf[2, 4, 6, 1],
hf[1, 5, 6, 1], hf[1, 5, 6, 2], hf[1, 5, 6, 3], hf[2, 5, 11, 1],
hf[2, 5, 6, 1], hf[1, 6, 11, 1], hf[1, 6, 11, 2], hf[1, 6, 11, 3],
hf[2, 6, 11, 1], hf[2, 6, 13, 1], hf[1, 11, 13, 1], hf[1, 11, 13, 2],
hf[1, 11, 13, 3], hf[2, 11, 13, 1], hf[1, 13, 8, 1], hf[1, 13, 12, 1],
hf[1, 13, 8, 2], hf[1, 8, 9, 1], hf[1, 6, 7, 1],
hf[1, 6, 7, 2], hf[1, 7, 6, 1], hf[1, 7, 11, 1], hf[1, 7, 11, 2]}*).


You can then equate these element by element using Thread:

Thread[funcs=somethings]


what I just did is I set the function hf to have specific values corresponding to the set of arguments, i.e. hf[1, 1, 2, 1] will evaluate to its value, here something1. This may not be what you want (here I add my confusion to the rest of the people) in which case I suggest you keep the lists curveIndexList and somethings separate.

If you want to select some elements or find their positions based on some rules. Position is good for that. In your first example, you are looking for

pos=Position[funcs, hf[2, _, _, _]]

(*{{3}, {4}, {7}, {10}, {11}, {12}, {16}, {17}, {21}, {22}, {26}}*)


i.e. the places where the functions whose first argument is 2. You can write this pattern more compactly like hf[2, __] or replace it to one of your other patterns. You can then take these positions and extract the relevant values from somethings:

Extract[somethings, pos]

(*{something3, something4, something7, something10, something11, \
something12, something16, something17, something21, something22, \
something26}*)

-

It's a little hard to tell what you are looking for. You ask: "could you work directly on the variable name indices? Here's one way to define indices with names and then use the names to index:

list = {bob = 1, pete = 2, henry = 3, bill = 4};
data = {5, 4, 2, 3};
data[[pete]]
4

-

This is only a partial answer to your question, which is rather open ended. You really need to become familiar with Mathematica's functional programming tools. For example, consider the power of Apply, i.e., @@:

List @@ hf[1, 11, 13, 1]


{1, 11, 13, 1}

hf @@ {1, 13, 12, 1}


hf[1, 13, 12, 1]

Also Part, i.e., [[ ]], which is a major tool for working with indices, works on any head.

hf[1, 11, 13, 1][[2]]

11

There are many other functional tools that could simplify your work. Perhaps others with discuss them in additional answers.

-
I"m sorry, it still isn't clear what you mean. Here's what you might do: make up a simple example (with only 1 or 2 indices) and 4 or 5 pieces of data and make it very precise what you want to accomplish. If we can't understand the question, we can't help. –  bill s Jul 5 '13 at 15:50

You can use variable index in this way.

state = {good, bad, edit};
temp = {hot, cold, normal};
data = Table[f[RandomChoice[state], RandomChoice[temp]], {i, 1, 10}]

hot = Cases[data, f[state_, temp_] /; temp == hot]

-

It seems unnecessary to encode the properties with meaningless integers, when you could use the property names directly in your example:

hf["bedding", "upper lith", "third B", "fourth A"] = {{30, -40}, {60, -50}};
hf["bedding", "second D", "third E", "fourth A"] = {{30, -50}, {60, -60}};
hf["bedding", "second D", "third E", "fourth B"] = {{70, -45}, {90, -40}};
hf["bedding", "second E", "third F", "fourth A"] = {{30, -65}, {60, -78}};
hf["fault", "second D", "third F", "fourth A"] = {{60, -78}, {65, -40}};

Last /@ Cases[DownValues[hf], _?(MemberQ[#, "second D" | "third D", Infinity] &), 1]
(* {{{30, -50}, {60, -60}}, {{70, -45}, {90, -40}}, {{60, -78}, {65, -40}}} *)


Or you could use key -> value rules (like options), and order would not matter.

hf[feature -> "bedding", layer -> "upper", prop3 -> "type B", prop4 -> "type A"]


with the appropriate terminology (which I don't know at all).

-
+1 for potentially decyphering what the question is- i thought the numbers where values that the function actually used, not labels. –  gpap Jul 6 '13 at 10:19