1
$\begingroup$

I have the following lists:

l1 = {{"letter.a.a", "1"}, {"letter.b.b", "1"}, {"letter.c.c", 
    "1"}, {"letter.d.d", "1"}, {"letter.e.e", "1"}, {"letter.f.f", 
    "1"}};
l2 = {{"f", 10}, {"c", 9}, {"e", 8}, {"b", 7}, {"d", 6}, {"a", 5}};

I want to replace the integers in l2 with "1"s in l1 appropriately such that I get:

{{"letter.a.a", 5}, {"letter.b.b", 7}, {"letter.c.c", 
        9}, {"letter.d.d", 6}, {"letter.e.e", 8}, {"letter.f.f", 
        10}}

Given the strings in l1 and l2 are slightly different I wonder how one can do this?

Update: In a more complex system I have:

l1 = {{"Food.ALMOND.ALMONDCINNAMON", 
   "1"}, {"Food.BLACK_CURRANT.BLACK_CURRANTCORN", 
   "1"}, {"Food.BELL_PEPPER.BELL_PEPPERLIME", "1"}}
l2 = {{"BLACK_CURRANTCORN", 4}, {"BELL_PEPPERLIME", 
   3}, {"ALMONDCINNAMON", 2}}

Here strings are words that need to be separated. How would one solve it for such lists? I think StringTake method fails for this.

$\endgroup$
2
$\begingroup$
assoc = Association[Rule @@@ l2];
l3 = l1;
l3[[All, 2]] = assoc /@ StringTake[l1[[All, 1]], -1] ;
l3

{{"letter.a.a", 5}, {"letter.b.b", 7}, {"letter.c.c", 9}, {"letter.d.d", 6}, {"letter.e.e", 8}, {"letter.f.f", 10}}

Alternatively,

l3 = l1;
l3[[All, 2]] = assoc /@ StringSplit[l1[[All, 1]], "."][[All, -1]];
l3

same result

Update:

ClearAll[f]
f = Module[{assoc = Association[Rule @@@ #2], l3 = #}, 
    l3[[All, 2]] = assoc /@ StringSplit[l3[[All, 1]], "."][[All, -1]];l3] &;

l1b = {{"Food.ALMOND.ALMONDCINNAMON", "1"}, {"Food.BLACK_CURRANT.BLACK_CURRANTCORN", "1"}, 
  {"Food.BELL_PEPPER.BELL_PEPPERLIME", "1"}};
l2b = {{"BLACK_CURRANTCORN", 4}, {"BELL_PEPPERLIME", 3}, {"ALMONDCINNAMON", 2}};


f[l1, l2]

{{"Food.ALMOND.ALMONDCINNAMON", 2}, {"Food.BLACK_CURRANT.BLACK_CURRANTCORN", 4}, {"Food.BELL_PEPPER.BELL_PEPPERLIME", 3}}

$\endgroup$
  • $\begingroup$ I see, so the main method is to use StringTake, but what if the system is more complex? i.e. suppose we have words. Let me make a edit for more generalised case. $\endgroup$ – William Jan 15 at 16:58
  • $\begingroup$ I just updated the question, please see. $\endgroup$ – William Jan 15 at 17:04
  • 1
    $\begingroup$ @William, updated. $\endgroup$ – kglr Jan 15 at 17:17
2
$\begingroup$

Just for fun, Another possibility might be

l1[[All, 2]]=Flatten[StringCases[First@#,"letter." ~~ c_ :> c]& /@ l1] /. (Rule @@@ l2)

which make l1 as

{{"letter.a.a", 5}, {"letter.b.b", 7}, {"letter.c.c", 
  9}, {"letter.d.d", 6}, {"letter.e.e", 8}, {"letter.f.f", 10}}

I think @kglr using association looks more direct.

$\endgroup$
0
$\begingroup$

Just for fun also :)

Map[{#[[1, 1]], #[[2, 2]]} &, GatherBy[Flatten[{l1, l2}, 1], (Last@StringSplit[#[[1]], "."]) &]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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