Function Repository Resource:

JoinRest

Source Notebook

An operator that performs a Join of its argument with the sequence of lists it is provided

Contributed by: Seth J. Chandler

ResourceFunction["JoinRest"][list]

gives an operator that will join list with the sequence of lists it is given.

Details and Options

When used in conjunction with associations, ResourceFunction["JoinRest"] can be thought of as creating an Association of key-value pairs kv that will augment the output Association if and only if the Join of whatever arguments the operator encounters fail to otherwise contain a key-value pair with a key of k.
The argument need not have head List. All subsequent expressions will be joined to it, provided they have the same head.

Examples

Basic Examples (2) 

JoinRest uses Join to join its argument {3,4} with whatever else it encounters, which you may think of as the "Rest" of the Join:

In[1]:=
ResourceFunction["JoinRest"][{3, 4}][{5, 6, 7}, {8, 9, 10, 11}]
Out[1]=

JoinRest applied to an Association creates an operator that will add key-value pairs to the Join of the argument it is passed, but only if those joined associations fail to contain a key present in the association to which JoinRest was applied:

In[2]:=
ResourceFunction["JoinRest"][<|"a" -> 0, "b" -> 0, "c" -> 0|>][
 Association["a" -> 7, "b" -> 9]]
Out[2]=

Scope (3) 

The operator created by JoinRest using an Association can accept a sequence of associations:

In[3]:=
ResourceFunction["JoinRest"][<|"a" -> 0, "b" -> 0, "c" -> 0|>][
 Association["a" -> 7, "b" -> 9], Association["a" -> -8, "c" -> 3]]
Out[3]=

If JoinRest has no argument, it operates as an identity on the data it is given:

In[4]:=
ResourceFunction["JoinRest"][][Association["a" -> 7, "b" -> 9]]
Out[4]=

If JoinRest has a sequence of associations as its argument, it will use the last value for any key it encounters in that sequence as a basis for adding key-value pairs:

In[5]:=
ResourceFunction["JoinRest"][<|"a" -> 0|>, <|"a" -> 4, "c" -> -2|>][
 Association["b" -> 9], Association["b" -> -8, "c" -> 3]]
Out[5]=

Applications (1) 

JoinRest can be right-composed with Counts to create an Association that obtains the number of every anticipated value in an expression:

In[6]:=
Query[Counts/*
   ResourceFunction[
    "JoinRest"][<|"a" -> 0, "b" -> 0, "c" -> 0|>]][{"a", "b", "a", "b", "a", "a", "a", "b"}]
Out[6]=

Properties and Relations (1) 

JoinRest works similarly to Merge with a First combiner function:

In[7]:=
With[{data = {"a", "b", "a", "b", "a", "a", "a", "b"}, default = <|"a" -> 0, "b" -> 0, "c" -> 0|>}, SameQ[Query[Counts/*ResourceFunction["JoinRest"][default]][data], Merge[{Query[Counts][data], default}, First]
  ]
 ]
Out[7]=

JoinRest is very similar to the resource function JoinMost. In JoinRest its argument is placed first in the Join; in JoinMost its argument is placed last in the Join.

Possible Issues (1) 

JoinRest, like Join, will fail to evaluate if the heads of the expressions to be joined differ from one another:

In[8]:=
ResourceFunction["JoinRest"][{1, 2, 3}][Association["a" -> 2]]
Out[8]=

Neat Examples (1) 

Insert JoinRest to a pipeline of operators created by Query, such that the count of various categories that survived and died on the Titanic defaults to 0:

In[9]:=
formatting = Row[{Labeled[#1, "ugly"], Labeled[#2, "nicer"]}, Spacer[6]] &;
In[10]:=
Module[{noMaleSurvivors = Query[Select[Not[#sex === "male" && #survived] &]][
    ExampleData[{"Dataset", "Titanic"}]], uglyQuery, prettyQuery, survivedString = (If[#survived, "survived", "died"] &), f1 = GroupBy[#class &], f2 = GroupBy[#sex &]/*KeySort,
  f3 = Counts/*KeySort,
  joiner = ResourceFunction["JoinRest"][
    Association["survived" -> 0, "died" -> 0]]},
 uglyQuery = Query[f1, f2, f3, survivedString];
 prettyQuery = Query[f1, f2, Insert[f3, joiner, 2], survivedString]; formatting[uglyQuery[noMaleSurvivors], prettyQuery[noMaleSurvivors]]
 ]
Out[10]=

Publisher

Seth J. Chandler

Version History

  • 1.0.0 – 24 June 2019

Related Resources

License Information