5
$\begingroup$

I wouldn't be surprised if the title question is confusing, so I'll try to elaborate by way of example.

Consider the list

person = {firstName, lastName, dateOfBirth, occupation, ..., country}

where each element of person is a String. I have a larger list, people, consisting of all lists person containing varying amounts of information. All person lists include first and last names and country, but not all have the DOB or occupation. I don't particularly care about these latter two entries. Other person lists have even more information between occupation and country (denoted by ...) that I would like to ignore.

I want to generate a list of pairs consisting of the StringRiffled first and last names, and the country, so that each person list is transformed to

{fullName, country}

Getting the names set up is easy using Slots, but I can't think of a good way to get the country in a consistent way. I had thought to try

{StringRiffle[{#1, #2}], #(-1)} & @@ # & /@ people
(* but the second entry is -1 times the first name ... *)

and

{StringRiffle[{#1, #2}], Slot[-1]} & @@ # & /@ people
(* but the argument to Slot must be non-negative ... *)

Is there some way of using Slot to this end? I'm of course open to other simpler suggestions.

$\endgroup$
7
$\begingroup$

As you already observed, Slot[-1] is not valid syntax in the same way as Slot[1]. The only way I can think of to do what you want, is to catch all arguments in a list with SlotSequence and then take the last Part:

{##}[[-1]] & @@ Range[5]

5

However, for stuff like this, I'd recommend using Associations instead, since then you can index by name instead of by integer positions and it's much easier to skip parts of the data:

people = {
   <|"FirstName" -> "John", "LastName" -> "Doe", "DoB" -> Yesterday, "Country" -> "Somewhere"|>
};
{StringRiffle[{#FirstName, #LastName}], #Country} & /@ people

{{"John Doe", "Somewhere"}}

It makes it easier to understand the code as well.

| improve this answer | |
$\endgroup$
7
$\begingroup$
people = {
   {firstName1, lastName1, dateOfBirth1, occupation1, country1},
   {firstName2, lastName2, , occupation2, country2}, 
   {firstName3, lastName3, dateOfBirth3, , country3}};

{StringRiffle[#[[1 ;; 2]]], #[[-1]]} & /@ people

(* {{"firstName1 lastName1", country1}, {"firstName2 lastName2", 
  country2}, {"firstName3 lastName3", country3}} *)
| improve this answer | |
$\endgroup$
5
$\begingroup$

I recommend using the operator form of Replace for these tasks, because in those circumstances you can use patterns and give parts of the sequence names. If you must use the @@, you can compose with List:

List /* Replace[{firstName_, lastName_, ___, country_} :>
    {StringRiffle[{firstName, lastName}], country}] @@ 
 {"John", "Doe", "random", "dumb", "stuff", "Burkina Faso"}
(* {"John Doe", "Burkina Faso"} *) 
| improve this answer | |
$\endgroup$
4
$\begingroup$
{StringRiffle[{#1, #2}], #3}& @@@ people[[All, {1,2,-1}]]

{{John Doe, Canada}, {firstName2 lastName2, country2}, {firstName3 lastName3, country3}}

Alternatively:

{StringRiffle[{#2, #3}], #1}&@@@(RotateRight/@people)

data

people = {
          {John, Doe, dateOfBirth1, occupation1, Canada},
          {firstName2, lastName2, , occupation2, martialStatus,country2}, 
          {firstName3, lastName3, dateOfBirth3, martialStatus , sex, country3}
          };
| improve this answer | |
$\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.