10
$\begingroup$

Each week I import a dataset, and every week the dataset differs in length (the number of records). After the import I need to do some transformations. One of these transformations is the ReplaceAll.

problem: when the number of records is the same length of the number of parameters in de transformations, the ReplaceAll won't give the desired output.

For example:

data1 = {{"A1", "B1", "C1", "D1", "E1"}, {"A2", "B2", "C2", "D2", 
   "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", "B4", "C4", "D4", 
   "E4"}, {"A5", "B5", "C5", "D5", "E5"}};

data1 /. {a_ , b_, c_ , d_ , e_} -> {"T", a , b, c, d, e}

The output is:

{"T", {"A1", "B1", "C1", "D1", "E1"}, {"A2", "B2", "C2", "D2", "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", "B4", "C4", "D4", "E4"}, {"A5", "B5", "C5", "D5", "E5"}}

When the number of records differ from the number of parameters in the ReplaceAll function, like this:

data2 = {{"A1", "B1", "C1", "D1", "E1"}, {"A2", "B2", "C2", "D2", 
   "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", "B4", "C4", "D4", 
   "E4"}};

data2 /. {a_ , b_, c_ , d_ , e_} -> {"T", a , b, c, d, e}

Now I get the output I want.

{{"T", "A1", "B1", "C1", "D1", "E1"}, {"T", "A2", "B2", "C2", "D2", "E2"}, {"T", "A3", "B3", "C3", "D3", "E3"}, {"T", "A4", "B4", "C4", "D4", "E4"}}

The same is truth for a list with six records:

data3 = {{"A1", "B1", "C1", "D1", "E1"}, {"A2", "B2", "C2", "D2", 
   "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", "B4", "C4", "D4", 
   "E4"}, {"A5", "B5", "C5", "D5", "E5"}, {"A6", "B6", "C6", "D6", 
   "E6"}}

data3 /. {a_ , b_, c_ , d_ , e_} -> {"T", a , b, c, d, e}

{{"T", "A1", "B1", "C1", "D1", "E1"}, {"T", "A2", "B2", "C2", "D2", "E2"}, {"T", "A3", "B3", "C3", "D3", "E3"}, {"T", "A4", "B4", "C4", "D4", "E4"}, {"T", "A5", "B5", "C5", "D5", "E5"}, {"T", "A6", "B6", "C6", "D6", "E6"}}

Who has a suggestion for this problem?

$\endgroup$

6 Answers 6

9
$\begingroup$

Use Replace with a level specification instead:

data1 = {
    {"A1","B1","C1","D1","E1"},
    {"A2","B2","C2","D2","E2"},
    {"A3","B3","C3","D3","E3"},
    {"A4","B4","C4","D4","E4"},
    {"A5","B5","C5","D5","E5"}
};

Replace[
    data1,
    {a_,b_,c_,d_,e_}->{"T",a,b,c,d,e},
    {1}
]

{{"T", "A1", "B1", "C1", "D1", "E1"}, {"T", "A2", "B2", "C2", "D2", "E2"}, {"T", "A3", "B3", "C3", "D3", "E3"}, {"T", "A4", "B4", "C4", "D4", "E4"}, {"T", "A5", "B5", "C5", "D5", "E5"}}

$\endgroup$
6
$\begingroup$

Try Prepend

Prepend[#, "T"] & /@ data1

{{"T", "A1", "B1", "C1", "D1", "E1"}, {"T", "A2", "B2", "C2", "D2", "E2"}, {"T", "A3", "B3", "C3", "D3", "E3"}, {"T", "A4", "B4", "C4", "D4", "E4"}, {"T", "A5", "B5", "C5", "D5", "E5"}}

Besides, {a_ , b_, c_ , d_ , e_} -> {"T", a , b, c, d, e} can be written as {a__} -> {"T", a} , if the list is not empty.

Or you can try

# /. {a__} :> {"T", a} & /@ {{"A1", "B1", "C1", "D1", "E1"}, {"A2", 
            "B2", "C2", "D2", "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", 
            "B4", "C4", "D4", "E4"}, {"A5", "B5", "C5", "D5", "E5"}}
$\endgroup$
5
$\begingroup$

It is because _ operator starts at top where it found List and only if number of elements in list are same as _(as a requirement of _), it will recognize it otherwise it will go down to elements of each list. Say you do a small test,

data2 /. {a_, b_, c_, d_, e_} /; ListQ[a] -> {"T", a, b, c, d, e}

It returns,

{{"A1", "B1", "C1", "D1", "E1"}, {"A2", "B2", "C2", "D2", 
  "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", "B4", "C4", "D4", 
  "E4"}}

Nothing processed because pattern didn't match.

To solve it, something on these line,

data2 //. {a___, {b_, c_, d_, e_, f_}, 
   g___} :> {a, {"T", b, c, d, e, f}, g}

{{"T", "A1", "B1", "C1", "D1", "E1"}, {"T", "A2", "B2", "C2", "D2", 
  "E2"}, {"T", "A3", "B3", "C3", "D3", "E3"}, {"T", "A4", "B4", "C4", 
  "D4", "E4"}}
$\endgroup$
1
  • $\begingroup$ Oke, thanks, But do you have a solution for my problem $\endgroup$ Commented Nov 9, 2020 at 13:28
2
$\begingroup$
list =
  {{"A1", "B1", "C1", "D1", "E1"},
   {"A2", "B2", "C2", "D2", "E2"},
   {"A3", "B3", "C3", "D3", "E3"},
   {"A4", "B4", "C4", "D4", "E4"},
   {"A5", "B5", "C5", "D5", "E5"}};

Using ReplaceAll with AtomQ

list /. {a__?AtomQ} :> {"T", a} // MatrixForm

enter image description here

Using Cases

Cases[list, a_ :> Prepend[a, "T"]] // MatrixForm

enter image description here

$\endgroup$
2
$\begingroup$
list =
  {{"A1", "B1", "C1", "D1", "E1"},
   {"A2", "B2", "C2", "D2", "E2"},
   {"A3", "B3", "C3", "D3", "E3"},
   {"A4", "B4", "C4", "D4", "E4"},
   {"A5", "B5", "C5", "D5", "E5"}};

Using ReplaceList:

ReplaceList[list, {___, s : {a_, b__}, ___} :> Prepend[s, "T"]] // MatrixForm

enter image description here

$\endgroup$
2
$\begingroup$
data1 = {{"A1", "B1", "C1", "D1", "E1"}, {"A2", "B2", "C2", "D2", 
    "E2"}, {"A3", "B3", "C3", "D3", "E3"}, {"A4", "B4", "C4", "D4", 
    "E4"}, {"A5", "B5", "C5", "D5", "E5"}};

data1 /. x_?VectorQ :> {"T"}~Join~x

{{"T", "A1", "B1", "C1", "D1", "E1"}, {"T", "A2", "B2", "C2", "D2",
"E2"}, {"T", "A3", "B3", "C3", "D3", "E3"}, {"T", "A4", "B4", "C4",
"D4", "E4"}, {"T", "A5", "B5", "C5", "D5", "E5"}}


In human language the above will be parsed roughly as:

If x_ matches a vector of elements then prepend "T" to this vector called x.

In the example posted by OP, {a_, b_, c_, d_, e_} would match five items, including five lists (if that is the case). When that happens, the replacements happen at the main level as opposed to the sublist level where these are intended. A further differentiation must be included to limit replacements to the sublist level only.

$\endgroup$

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.