Associative array/Merging

From Rosetta Code
Revision as of 23:02, 4 August 2021 by Alextretyak (talk | contribs) (Added 11l)
Task
Associative array/Merging
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Define two associative arrays, where one represents the following "base" data:

Key Value
"name" "Rocket Skates"
"price" 12.75
"color" "yellow"

And the other represents "update" data:

Key Value
"price" 15.25
"color" "red"
"year" 1974

Merge these into a new associative array that contains every key found in either of the source ones. Each key should map to the value in the second (update) table if that exists, or else to the value in the first (base) table. If possible, do this in a way that does not mutate the original two associative arrays. Obviously this should be done in a way that would work for any data, not just the specific data given here, but in this example the result should be:

Key Value
"name" "Rocket Skates"
"price" 15.25
"color" "red"
"year" 1974



11l

Translation of: Python

<lang 11l>V base = [‘name’ = ‘Rocket Skates’, ‘price’ = ‘12.75’, ‘color’ = ‘yellow’] V update = [‘price’ = ‘15.25’, ‘color’ = ‘red’, ‘year’ = ‘1974’]

V result = copy(base) result.update(update)

print(result)</lang>

Output:
[color = red, name = Rocket Skates, price = 15.25, year = 1974]

Ada

<lang Ada>with Ada.Text_Io; with Ada.Containers.Indefinite_Ordered_Maps;

procedure Merge_Maps is

  use Ada.Text_Io;
  type Key_Type   is new String;
  type Value_Type is new String;
  package Maps is
    new Ada.Containers.Indefinite_Ordered_Maps (Key_Type     => Key_Type,
                                                Element_Type => Value_Type);
  use Maps;
  function Merge (Original : Map; Update : Map) return Map is
     Result : Map    := Original;
     Cur    : Cursor := Update.First;
  begin
     while Has_Element (Cur) loop
        if Original.Contains (Key (Cur)) then
           Result.Replace_Element (Result.Find (Key (Cur)),
                                   Element (Cur));
        else
           Result.Insert (Key (Cur), Element (Cur));
        end if;
        Next (Cur);
     end loop;
     return Result;
  end Merge;
  procedure Put_Map (M : Map) is
     Cur : Cursor := M.First;
  begin
     while Has_Element (Cur) loop
        Put (String (Key (Cur)));
        Set_Col (12);
        Put (String (Element (Cur)));
        New_Line;
        Next (Cur);
     end loop;
  end Put_Map;
  Original : Map;
  Update   : Map;
  Result   : Map;

begin

  Original.Insert ("name", "Rocket Skates");
  Original.Insert ("price", "12.75");
  Original.Insert ("color", "yellow");
  Update.Insert ("price", "15.25");
  Update.Insert ("color", "red");
  Update.Insert ("year", "1974");
  Result := Merge (Original, Update);
  Put_Line ("Original:");
  Put_Map (Original);
  New_Line;
  Put_Line ("Update:");
  Put_Map (Update);
  New_Line;
  Put_Line ("Result of merge:");
  Put_Map (Result);
  New_Line;

end Merge_Maps;</lang>

Output:
Original:
color      yellow
name       Rocket Skates
price      12.75

Update:
color      red
price      15.25
year       1974

Result of merge:
color      red
name       Rocket Skates
price      15.25
year       1974

ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

Uses the associative array implementations in ALGOL_68/prelude. <lang algol68># associative array merging #

  1. the modes allowed as associative array element values - change to suit #

MODE AAVALUE = UNION( STRING, INT, REAL );

  1. the modes allowed as associative array element keys - change to suit #

MODE AAKEY = STRING;

  1. initial value for an array element #

AAVALUE init element value = "";

  1. include the associative array code #

PR read "aArrayBase.a68" PR

  1. adds or replaces all elements from b into a #

PRIO UPDATE = 9; OP UPDATE = ( REF AARRAY a, REF AARRAY b )REF AARRAY: BEGIN

   REF AAELEMENT e := FIRST b;
   WHILE e ISNT nil element DO
       a // key OF e := value OF e;
       e := NEXT b
   OD;
   a

END # UPDATE # ;

  1. construct the associative arrays for the task #

REF AARRAY a := INIT LOC AARRAY; REF AARRAY b := INIT LOC AARRAY; a // "name"  := "Rocket Skates"; a // "price" := 12.75; a // "color" := "yellow"; b // "price" := 15.25; b // "color" := "red"; b // "year"  := 1974;

  1. merge the arrays #

REF AARRAY c := INIT LOC AARRAY; c UPDATE a UPDATE b;

  1. show the merged array #

REF AAELEMENT e := FIRST c; WHILE e ISNT nil element DO

   print( ( key OF e
          , ": "
          , CASE value OF e
              IN (STRING s): s
               , (INT    i): whole( i, 0 )
               , (REAL   r): fixed( r, -12, 2 )
             OUT "????"
            ESAC
          , newline
          )
        );
   e := NEXT c

OD</lang>

Output:
name: Rocket Skates
year: 1974
price:        15.25
color: red

AppleScript

The method with AppleScript "records" is to concatenate them. The result is a third record containing the labels from both contributors, the values from the record to the left of the operator being kept where labels are shared. The bars with some of the labels below are to distinguish them as "user" labels from tokenised ones that are provided as standards for use by scriptable applications and scripting additions. However, merging records works with tokenised labels too.

<lang applescript>set baseRecord to {|name|:"Rocket Skates", price:12.75, |color|:"yellow"} set updateRecord to {price:15.25, |color|:"red", |year|:1974}

set mergedRecord to updateRecord & baseRecord return mergedRecord</lang>

Output:

<lang applescript>{price:15.25, |color|:"red", |year|:1974, |name|:"Rocket Skates"}</lang>

Arturo

<lang rebol>details: #[name: "Rocket Skates" price: 12.75 colour: 'yellow] newDetails: extend details #[price: 15.25 colour: 'red year: 1974]

print newDetails</lang>

Output:
[name:Rocket Skates price:15.25 colour:red year:1974]

AutoHotkey

<lang AutoHotkey>merge(base, update){ Merged  := {} for k, v in base Merged[k] := v for k, v in update Merged[k] := v return Merged }</lang> Examples:<lang AutoHotkey>base := {"name":"Rocket Skates", "price":12.75, "color":"yellow"} update := {"price":15.25, "color":"red", "year":1974} Merged := merge(base, update) for k, v in Merged result .= k " : " v "`n" MsgBox % result</lang>

Outputs:
color : red
name : Rocket Skates
price : 15.25
year : 1974

AWK

<lang AWK>

  1. syntax: GAWK -f ASSOCIATIVE_ARRAY_MERGING.AWK
  2. sorting:
  3. PROCINFO["sorted_in"] is used by GAWK
  4. SORTTYPE is used by Thompson Automation's TAWK

BEGIN {

   PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
   arr1["name"] = "Rocket Skates"
   arr1["price"] = "12.75"
   arr1["color"] = "yellow"
   show_array(arr1,"base")
   arr2["price"] = "15.25"
   arr2["color"] = "red"
   arr2["year"] = "1974"
   show_array(arr2,"update")
   for (i in arr1) { arr3[i] = arr1[i] }
   for (i in arr2) { arr3[i] = arr2[i] }
   show_array(arr3,"merged")
   exit(0)

} function show_array(arr,desc, i) {

   printf("\n%s array\n",desc)
   for (i in arr) {
     printf("%-5s : %s\n",i,arr[i])
   }

} </lang>

Output:
base array
color : yellow
name  : Rocket Skates
price : 12.75

update array
color : red
price : 15.25
year  : 1974

merged array
color : red
name  : Rocket Skates
price : 15.25
year  : 1974

B4X

<lang b4x>Dim m1 As Map = CreateMap("name": "Rocket Skates", "price": 12.75, "color": "yellow") Dim m2 As Map = CreateMap("price": 15.25, "color": "red", "year": 1974) Dim merged As Map merged.Initialize For Each m As Map In Array(m1, m2) For Each key As Object In m.Keys merged.Put(key, m.Get(key)) Next Next Log(merged)</lang>

BaCon

<lang bacon>DECLARE base$, update$, merge$ ASSOC STRING

base$("name") = "Rocket Skates" base$("price") = "12.75" base$("color") = "yellow"

PRINT "Base array" FOR x$ IN OBTAIN$(base$)

   PRINT x$, " : ", base$(x$)

NEXT

update$("price") = "15.25" update$("color") = "red" update$("year") = "1974"

PRINT NL$, "Update array" FOR x$ IN OBTAIN$(update$)

   PRINT x$, " : ", update$(x$)

NEXT

merge$() = base$() merge$() = update$()

PRINT NL$, "Merged array" FOR x$ IN OBTAIN$(merge$)

   PRINT x$, " : ", merge$(x$)

NEXT</lang>

Output:
Base array
name : Rocket Skates
color : yellow
price : 12.75

Update array
year : 1974
color : red
price : 15.25

Merged array
name : Rocket Skates
year : 1974
color : red
price : 15.25

C++

<lang cpp>#include <iostream>

  1. include <string>
  2. include <map>

template<typename map_type> map_type merge(const map_type& original, const map_type& update) {

   map_type result(update);
   result.insert(original.begin(), original.end());
   return result;

}

int main() {

   typedef std::map<std::string, std::string> map;
   map original{
       {"name", "Rocket Skates"},
       {"price", "12.75"},
       {"color", "yellow"}
   };
   map update{
       {"price", "15.25"},
       {"color", "red"},
       {"year", "1974"}
   };
   map merged(merge(original, update));
   for (auto&& i : merged)
       std::cout << "key: " << i.first << ", value: " << i.second << '\n';
   return 0;

}</lang>

Output:
key: color, value: red
key: name, value: Rocket Skates
key: price, value: 15.25
key: year, value: 1974

C#

<lang csharp>using System; using System.Collections.Generic; using System.Linq;

public class Program {

   public static void Main() {
       var baseData = new Dictionary<string, object> {
           ["name"] = "Rocket Skates",
           ["price"] = 12.75,
           ["color"] = "yellow"
       };
       var updateData = new Dictionary<string, object> {
           ["price"] = 15.25,
           ["color"] = "red",
           ["year"] = 1974
       };
       var mergedData = new Dictionary<string, object>();
       foreach (var entry in baseData.Concat(updateData)) {
           mergedData[entry.Key] = entry.Value;
       }
       foreach (var entry in mergedData) {
           Console.WriteLine(entry);
       }
  }

}</lang>

Output:
[name, Rocket Skates]
[price, 15.25]
[color, red]
[year, 1974]

Clojure

<lang Clojure> (defn update-map [base update]

 (merge base update))
 (update-map {"name"  "Rocket Skates"
              "price" "12.75"
              "color" "yellow"}
             {"price" "15.25"
              "color" "red"
              "year"  "1974"})

</lang>

Output:
{"name" "Rocket Skates", "price" "15.25", "color" "red", "year" "1974"}

Crystal

<lang crystal>base = {"name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"} update = { "price" => 15.25, "color" => "red", "year" => 1974 }

puts base.merge(update)</lang>

Output:
{"name" => "Rocket Skates", "price" => 15.25, "color" => "red", "year" => 1974}

Dart

<lang javascript> main() { var base = { 'name': 'Rocket Skates', 'price': 12.75, 'color': 'yellow' };

var newData = { 'price': 15.25, 'color': 'red', 'year': 1974 };

var updated = Map.from( base ) // create new Map from base ..addAll( newData ); // use cascade operator to add all new data

assert( base.toString() == '{name: Rocket Skates, price: 12.75, color: yellow}' ); assert( updated.toString() == '{name: Rocket Skates, price: 15.25, color: red, year: 1974}');


} </lang>

Delphi

Translation of: C#

<lang Delphi> program Associative_arrayMerging;

{$APPTYPE CONSOLE}

uses

 System.Generics.Collections;

type

 TData = TDictionary<string, Variant>;

var

 baseData, updateData, mergedData: TData;
 entry: string;

begin

 baseData := TData.Create();
 baseData.Add('name', 'Rocket Skates');
 baseData.Add('price', 12.75);
 baseData.Add('color', 'yellow');
 updateData := TData.Create();
 updateData.Add('price', 15.25);
 updateData.Add('color', 'red');
 updateData.Add('year', 1974);
 mergedData := TData.Create();
 for entry in baseData.Keys do
   mergedData.AddOrSetValue(entry, baseData[entry]);
 for entry in updateData.Keys do
   mergedData.AddOrSetValue(entry, updateData[entry]);
 for entry in mergedData.Keys do
   Writeln(entry, ' ', mergedData[entry]);
 mergedData.Free;
 updateData.Free;
 baseData.Free;
 Readln;

end.

</lang>

Output:
price 15,25
year 1974
color red
name Rocket Skates

Elixir

Elixir has a built-in hashmap type, called Map. <lang Elixir>base = %{name: "Rocket Skates", price: 12.75, color: "yellow"} update = %{price: 15.25, color: "red", year: 1974} result = Map.merge(base, update) IO.inspect(result)</lang>

Output:
%{color: "red", name: "Rocket Skates", price: 15.25, year: 1974}

The above sample uses atoms as the key type. If strings are needed, the base map would look like this: <lang Elixir>base = %{"name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"}</lang>

F#

<lang fsharp> type N = |Price of float|Name of string|Year of int|Colour of string let n=Map<string,N>[("name",Name("Rocket Skates"));("price",Price(12.75));("colour",Colour("yellow"))] let g=Map<string,N>[("price",Price(15.25));("colour",Colour("red"));("year",Year(1974))] let ng=(Map.toList n)@(Map.toList g)|>Map.ofList printfn "%A" ng </lang>

Output:
map
  [("colour", Colour "red"); ("name", Name "Rocket Skates");
   ("price", Price 15.25); ("year", Year 1974)]

// Minimum positive multiple in base 10 using only 0 and 1. Nigel Galloway: March 9th., 2020

Factor

The assoc-union word does this. assoc-union! is a variant that mutates the first associative array.

Works with: Factor version 0.99 2019-10-06

<lang factor>USING: assocs prettyprint ;

{ { "name" "Rocket Skates" } { "price" 12.75 } { "color" "yellow" } } { { "price" 15.25 } { "color" "red" } { "year" 1974 } } assoc-union .</lang>

Output:
V{
    { "name" "Rocket Skates" }
    { "price" 15.25 }
    { "color" "red" }
    { "year" 1974 }
}

Go

<lang go>package main

import "fmt"

type assoc map[string]interface{}

func merge(base, update assoc) assoc {

   result := make(assoc)
   for k, v := range base {
       result[k] = v
   }
   for k, v := range update {
       result[k] = v
   }
   return result

}

func main() {

   base := assoc{"name": "Rocket Skates", "price": 12.75, "color": "yellow"}
   update := assoc{"price": 15.25, "color": "red", "year": 1974}
   result := merge(base, update)
   fmt.Println(result)

}</lang>

Output:
map[color:red name:Rocket Skates price:15.25 year:1974]

Haskell

There are various approaches, all of which would be strictly typed.
For example, if we want to treat the input and output records as all sharing the same type: <lang haskell>data Item = Item

 { name :: Maybe String
 , price :: Maybe Float
 , color :: Maybe String
 , year :: Maybe Int
 } deriving (Show)

itemFromMerge :: Item -> Item -> Item itemFromMerge (Item n p c y) (Item n1 p1 c1 y1) =

 Item (maybe n pure n1) (maybe p pure p1) (maybe c pure c1) (maybe y pure y1)

main :: IO () main =

 print $
 itemFromMerge
   (Item (Just "Rocket Skates") (Just 12.75) (Just "yellow") Nothing)
   (Item Nothing (Just 15.25) (Just "red") (Just 1974))</lang>
Output:
Item {name = Just "Rocket Skates", price = Just 15.25, color = Just "red", year = Just 1974}

Icon and Unicon

<lang unicon>procedure main()

   local base, update, master, f, k
   base := table()
   base["name"] := "Rocket Skates"
   base["price"] := 12.75
   base["color"] := "yellow"
   update := table()
   update["price"] := 15.25
   update["color"] := "red"
   update["year"] := 1974
   master := table()
   every k := key((f := base | update)) do {
       master[k] := f[k]
   }
   every k := key(master) do {
       write(k, " = ", master[k])
   }

end</lang>

Output:
prompt$ unicon -s merge.icn -x
color = red
name = Rocket Skates
price = 15.25
year = 1974

J

<lang J> merge=: ,. NB. use: update merge original compress=: #"1~ ~:@:keys keys=: {. values=: {: get=: [: > ((i.~ keys)~ <)~ { values@:] NB. key get (associative array) pair=: [: |: <;._2;._2 </lang> Exercise the definitions. Interactive J prompts with 3 space indentation.

   ] D=: pair 0 :0
name;Rocket Skates;
price;12.75;
color;yellow;
)
┌─────────────┬─────┬──────┐
│name         │price│color │
├─────────────┼─────┼──────┤
│Rocket Skates│12.75│yellow│
└─────────────┴─────┴──────┘

   E=: pair 0 :0
price;15.25;
color;red;
year;1974;
)

   'color'get D
yellow

   'color'get E
red

   ] F=: E merge D
┌─────┬─────┬────┬─────────────┬─────┬──────┐
│price│color│year│name         │price│color │
├─────┼─────┼────┼─────────────┼─────┼──────┤
│15.25│red  │1974│Rocket Skates│12.75│yellow│
└─────┴─────┴────┴─────────────┴─────┴──────┘

   'color' get F
red

   ]G=: compress F
┌─────┬─────┬────┬─────────────┐
│price│color│year│name         │
├─────┼─────┼────┼─────────────┤
│15.25│red  │1974│Rocket Skates│
└─────┴─────┴────┴─────────────┘

   'no such key'get F
|index error: get
|   'no such key'    get F

   'color'get F
red

Java

<lang java>import java.util.*;

class MergeMaps {

   public static void main(String[] args) {
       Map<String, Object> base = new HashMap<>();
       base.put("name", "Rocket Skates");
       base.put("price", 12.75);
       base.put("color", "yellow");
       Map<String, Object> update = new HashMap<>();
       update.put("price", 15.25);
       update.put("color", "red");
       update.put("year", 1974);
       Map<String, Object> result = new HashMap<>(base);
       result.putAll(update);
       System.out.println(result);
   }

}</lang>

Output:
{name=Rocket Skates, color=red, year=1974, price=15.25}

JavaScript

<lang javascript>(() => {

   'use strict';
   console.log(JSON.stringify(
       Object.assign({}, // Fresh dictionary.
           { // Base.
               "name": "Rocket Skates",
               "price": 12.75,
               "color": "yellow"
           }, { // Update.
               "price": 15.25,
               "color": "red",
               "year": 1974
           }
       ), 
       null, 2
   ))

})();</lang>

Output:
{
  "name": "Rocket Skates",
  "price": 15.25,
  "color": "red",
  "year": 1974
}

jq

Mapping “associative array” to “JSON object” in the natural way, the specified operation corresponds exactly to addition in jq, so that if A and B are the first and second objects respectively, then the jq expression `A + B` will yield the required result (as a JSON object).

Julia

julia> dict1 = Dict("name" => "Rocket Skates", "price" => 12.75, "color" => "yellow")
Dict{String,Any} with 3 entries:
  "name"  => "Rocket Skates"
  "price" => 12.75
  "color" => "yellow"

julia> dict2 = Dict("price" => 15.25, "color" => "red", "year" => 1974)
Dict{String,Any} with 3 entries:
  "price" => 15.25
  "year"  => 1974
  "color" => "red"

julia> merge(dict1, dict2)
Dict{String,Any} with 4 entries:
  "name"  => "Rocket Skates"
  "price" => 15.25
  "year"  => 1974
  "color" => "red"

julia> merge(dict2, dict1)
Dict{String,Any} with 4 entries:
  "name"  => "Rocket Skates"
  "price" => 12.75
  "year"  => 1974
  "color" => "yellow"

julia> union(dict1, dict2)
6-element Array{Pair{String,Any},1}:
  "name" => "Rocket Skates"
 "price" => 12.75
 "color" => "yellow"
 "price" => 15.25
  "year" => 1974
 "color" => "red"

Kotlin

<lang scala> fun main() {

   val base = HashMap<String,String>()
   val update =  HashMap<String,String>()
   base["name"] = "Rocket Skates"
   base["price"] = "12.75"
   base["color"] = "yellow"
   update["price"] = "15.25"
   update["color"] = "red"
   update["year"] = "1974"
   val merged = HashMap(base)
   merged.putAll(update)
   println("base: $base")
   println("update: $update")
   println("merged: $merged")

} </lang>

Output:
base: {color=yellow, price=12.75, name=Rocket Skates}
update: {color=red, year=1974, price=15.25}
merged: {name=Rocket Skates, color=red, year=1974, price=15.25}

Lua

<lang Lua>base = {name="Rocket Skates", price=12.75, color="yellow"} update = {price=15.25, color="red", year=1974}

--clone the base data -- result = {} for key,val in pairs(base) do

   result[key] = val

end

--copy in the update data -- for key,val in pairs(update) do

   result[key] = val

end

--print the result -- for key,val in pairs(result) do

   print(string.format("%s: %s", key, val))

end</lang>

Output:
price: 15.25
color: red
year: 1974
name: Rocket Skates

Mathematica / Wolfram Language

<lang Mathematica>a1 = <|"name" -> "Rocket Skates", "price" -> 12.75, "color" -> "yellow"|>; a2 = <|"price" -> 15.25, "color" -> "red", "year" -> 1974|>; Merge[{a1, a2}, Last]</lang>

Output:
<|"name" -> "Rocket Skates", "price" -> 15.25, "color" -> "red", "year" -> 1974|>

MiniScript

MiniScript supports merging maps with the + operator. <lang MiniScript>base = {"name":"Rocket Skates", "price":12.75, "color":"yellow"} update = {"price":15.25, "color":"red", "year":1974}

result = base + update

print result</lang>

Output:
{"color": "red", "name": "Rocket Skates", "price": 15.25, "year": 1974}

Nim

<lang Nim>import tables

let t1 = {"name": "Rocket Skates", "price": "12.75", "color": "yellow"}.toTable let t2 = {"price": "15.25", "color": "red", "year": "1974"}.toTable

var t3 = t1 # Makes a copy. for key, value in t2.pairs:

 t3[key] = value

echo t3</lang>

Output:
{"name": "Rocket Skates", "year": "1974", "color": "red", "price": "15.25"}

Objective-C

Works with: Cocoa

<lang objc>#import <Foundation/Foundation.h>

int main(void) {

 @autoreleasepool {
   NSDictionary *base = @{@"name": @"Rocket Skates", @"price": @12.75, @"color": @"yellow"};
   NSDictionary *update = @{@"price": @15.25, @"color": @"red", @"year": @1974};
   
   NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithDictionary:base];
   [result addEntriesFromDictionary:update];
   
   NSLog(@"%@", result);
 }
 return 0;

}</lang>

Output:
{
    color = red;
    name = "Rocket Skates";
    price = "15.25";
    year = 1974;
}

OCaml

Original version by User:Vanyamil

Note that, given OCaml's strong typing, we must declare a type here for the 3-type data. In general, would need the specific data type for the task, or use a PPX rewriter (effectively a compiler middleware) that can rewrite code based on dynamic type extensions.

Helper code for all 3 versions: <lang OCaml> type ty =

   | TFloat of float
   | TInt of int
   | TString of string

type key = string type assoc = string * ty

let string_of_ty : ty -> string = function

   | TFloat x -> string_of_float x
   | TInt i -> string_of_int i
   | TString s -> s

let print_pair key el =

   Printf.printf "%s: %s\n" key (string_of_ty el)

</lang>

Association list : naive and functional approach. <lang OCaml> let l1 : assoc list = [

   ("name", TString "Rocket Skates");
   ("price", TFloat 12.75);
   ("color", TString "yellow")

] ;;

let l2 : assoc list = [

   ("price", TFloat 15.25);
   ("color", TString "red");
   ("year",  TInt 1974)

] ;;

let rec merge_assoc_list (base_list : assoc list) (add_list : assoc list) : assoc list =

   List.fold_left
       (fun l (key, val_) -> 
           (key, val_) :: (List.remove_assoc key l)
       )
       base_list
       add_list

let l' = merge_assoc_list l1 l2 ;; </lang>

Binary tree/Map functor : proper functional approach.

Works with: OCaml version above 4.03 for union function

<lang OCaml> module StringMap = Map.Make(String) ;;

let print_map = StringMap.iter print_pair ;;

let map_merge (base : ty StringMap.t) (add : ty StringMap.t) : ty StringMap.t =

   StringMap.union (fun key v1 v2 -> Some v2) base add

let m1 = StringMap.(

   empty 
   |> add "name" (TString "Rocket Skates")
   |> add "price" (TFloat 12.75)
   |> add "color" (TString "yellow")

) ;;

let m2 = StringMap.(

   empty 
   |> add "price" (TFloat 15.25)
   |> add "color" (TString "red")
   |> add "year" (TInt 1974)

) ;;

let m' = map_merge m1 m2 ;;

print_map m' ;; </lang>

Hash table : imperative/mutable approach. <lang OCaml> (* Updates the base table with the bindings from add *) let hash_merge (base : (string, ty) Hashtbl.t) (add : (string, ty) Hashtbl.t) : unit =

   Hashtbl.iter (Hashtbl.replace base) add

let print_hashtbl t =

   Hashtbl.iter print_pair t

let h1 : (string, ty) Hashtbl.t = Hashtbl.create 10 ;; Hashtbl.add h1 "name" (TString "Rocket Skates") ;; Hashtbl.add h1 "price" (TFloat 12.75) ;; Hashtbl.add h1 "color" (TString "yellow") ;;

let h2 : (string, ty) Hashtbl.t = Hashtbl.create 10 ;; Hashtbl.add h2 "price" (TFloat 15.25) ;; Hashtbl.add h2 "color" (TString "red") ;; Hashtbl.add h2 "year" (TInt 1974) ;;

hash_merge h1 h2 ;;

print_hashtbl h1 ;; </lang>

Ol

<lang scheme> (define a1 {

  'name    "Rocket Skates"
  'price   12.75
  'color   "yellow"

})

(define a2 {

  'price   15.25
  'color   "red"
  'year    1974 

})

(print "a1: " a1) (print "a2: " a2)

(define (collide a b) b) ; will use new key value (print "merged a1 a2: " (ff-union a1 a2 collide)) </lang>

Output:
a1: #ff((name . Rocket Skates) (price . 51/4) (color . yellow))
a2: #ff((price . 61/4) (color . red) (year . 1974))
merged a1 a2: #ff((name . Rocket Skates) (price . 61/4) (color . red) (year . 1974))

Perl

<lang perl>use strict; use warnings;

my %base = ("name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"); my %more = ("price" => 15.25, "color" => "red", "year" => 1974);

print "Update\n"; my %update = (%base, %more); printf "%-7s %s\n", $_, $update{$_} for sort keys %update;

print "\nMerge\n"; my %merge; $merge{$_} = [$base{$_}] for keys %base; push @{$merge{$_}}, $more{$_} for keys %more; printf "%-7s %s\n", $_, join ', ', @{$merge{$_}} for sort keys %merge;</lang>

Output:
Update
color   red
name    Rocket Skates
price   15.25
year    1974

Merge
color   yellow, red
name    Rocket Skates
price   12.75, 15.25
year    1974

Phix

<lang Phix>integer d1 = new_dict({{"name","Rocket Skates"},{"price",12.75},{"color","yellow"}}),

       d2 = new_dict({{"price",15.25},{"color","red"},{"year",1974}}),
       d3 = new_dict(d1)

function merger(object key, data, /*user_data*/) setd(key,data,d3) return 1 end function traverse_dict(merger,NULL,d2) include builtins/map.e ?pairs(d3)</lang>

Output:
{{"color","red"},{"name","Rocket Skates"},{"price",15.25},{"year",1974}}

Phixmonti

<lang Phixmonti>include ..\Utilitys.pmt

def scand /# dict key -- dict n #/

   0 var flag
   var ikey
   len for
       var i
       i 1 2 tolist sget
       ikey == if i var flag exitfor endif
   endfor
   flag

enddef


def getd /# dict key -- dict data #/

   scand
   dup if get 2 get nip else drop "Unfound" endif

enddef


def setd /# dict ( key data ) -- dict #/

   1 get rot swap
   scand
   rot swap
   dup if set else put endif

enddef

/# ---------- MAIN ---------- #/

( ( "name" "Rocket Skates" )

 ( "price" 12.75 )
 ( "color" "yellow" ) )

dup

( ( "price" 15.25 )

 ( "color" "red" )
 ( "year" 1974 ) )
 

len for

   get rot swap setd swap

endfor

swap

pstack </lang>

PHP

<lang php><? $base = array("name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"); $update = array("price" => 15.25, "color" => "red", "year" => 1974);

$result = $update + $base; // Notice that the order is reversed print_r($result); ?></lang>

Output:
Array
(
    [price] => 15.25
    [color] => red
    [year] => 1974
    [name] => Rocket Skates
)

Alternative: <lang php><? $base = array("name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"); $update = array("price" => 15.25, "color" => "red", "year" => 1974);

$result = array_merge($base, $update); print_r($result); ?></lang>

Output:
Array
(
    [name] => Rocket Skates
    [price] => 15.25
    [color] => red
    [year] => 1974
)

PureBasic

<lang PureBasic>NewMap m1.s() NewMap m2.s() NewMap m3.s()

m1("name")="Rocket Skates" m1("price")="12.75" m1("color")="yellow"

m2("price")="15.25" m2("color")="red" m2("year")="1974"

CopyMap(m1(),m3())

ForEach m2()

 m3(MapKey(m2()))=m2()

Next

ForEach m3()

 Debug MapKey(m3())+" : "+m3()

Next</lang>

Output:
price : 15.25
color : red
year : 1974
name : Rocket Skates

Python

As of Python 3.5, this can be solved with the dictionary unpacking operator.

Works with: Python version 3.5+

<lang Python>base = {"name":"Rocket Skates", "price":12.75, "color":"yellow"} update = {"price":15.25, "color":"red", "year":1974}

result = {**base, **update}

print(result)</lang>

Output:
{'name': 'Rocket Skates', 'price': 15.25, 'color': 'red', 'year': 1974}
Alternative

<lang Python>base = {"name":"Rocket Skates", "price":12.75, "color":"yellow"} update = {"price":15.25, "color":"red", "year":1974}

result = base.copy() result.update(update)

print(result)</lang>

Output:
{'name': 'Rocket Skates', 'price': 15.25, 'color': 'red', 'year': 1974}
New alternative using '|'

<lang python>Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license()" for more information. >>> base = {"name":"Rocket Skates", "price":12.75, "color":"yellow"} >>> update = {"price":15.25, "color":"red", "year":1974} >>> result = base | update >>> result {'name': 'Rocket Skates', 'price': 15.25, 'color': 'red', 'year': 1974} >>> </lang>

Racket

<lang racket>#lang racket/base

(require racket/hash)

(module+ test

 (require rackunit)
 (define base-data (hash "name"	"Rocket Skates"
                         "price"	12.75
                         "color"	"yellow"))
 (define update-data (hash "price"	15.25
                           "color"	"red"
                           "year"	1974))
 (hash-union base-data update-data #:combine (λ (a b) b)))

</lang>

Output:
'#hash(("color" . "red") ("name" . "Rocket Skates") ("price" . 15.25) ("year" . 1974))

Raku

(formerly Perl 6)

Works with: Rakudo version 2019.11

I must say I somewhat disagree with the terminology. The requested operation is an update not a merge. Demonstrate both an update and a merge. Associative arrays are commonly called hashes in Raku.

<lang perl6># Show original hashes say my %base = :name('Rocket Skates'), :price<12.75>, :color<yellow>; say my %update = :price<15.25>, :color<red>, :year<1974>;

  1. Need to assign to anonymous hash to get the desired results and avoid mutating
  2. TIMTOWTDI

say "\nUpdate:\n", join "\n", sort %=%base, %update;

  1. Same

say "\nUpdate:\n", {%base, %update}.sort.join: "\n";

say "\nMerge:\n", join "\n", sort ((%=%base).push: %update)».join: ', ';

  1. Same

say "\nMerge:\n", ({%base}.push: %update)».join(', ').sort.join: "\n";

  1. Demonstrate unmutated hashes

say "\n", %base, "\n", %update;</lang>

Output:
{color => yellow, name => Rocket Skates, price => 12.75}
{color => red, price => 15.25, year => 1974}

Update:
color	red
name	Rocket Skates
price	15.25
year	1974

Update:
color	red
name	Rocket Skates
price	15.25
year	1974

Merge:
color	yellow, red
name	Rocket Skates
price	12.75, 15.25
year	1974

Merge:
color	yellow, red
name	Rocket Skates
price	12.75, 15.25
year	1974

{color => yellow, name => Rocket Skates, price => 12.75}
{color => red, price => 15.25, year => 1974}

REXX

The REXX language has no native support to acquire the keys of an associate array after they have been defined,  
so it must be performed at definition time,   but there are function packages to perform this function.

Some extra coding was added to support adjustable (maximum) widths for the displaying of the associate array names, keys, and values.

The double quotes that surround the string (character) items (as shown in the task's preamble) weren't included for this presentation,
although they could easily be added. <lang rexx>/*REXX program merges two associative arrays (requiring an external list of indices). */ $.= /*define default value(s) for arrays. */ @.wAAn= 21; @.wKey= 7; @.wVal= 7 /*max widths of: AAname, keys, values.*/ call defAA 'base', "name Rocket Skates", 'price 12.75', "color yellow" call defAA 'update', "price 15.25", "color red", 'year 1974' call show 'base' call show 'update' call show 'new' exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ defAA: procedure expose $. @.; parse arg AAn; new= 'new' /*get AA name; set NEW.*/

        do j=2  to arg();   parse value arg(j)  with  key val   /*obtain key and value.*/
        $.AAn.key= val                          /*assign a  value  to a  key for AAn.  */
        if wordpos(key, $.AAN.?keys)==0  then $.AAn.?keys= $.AAn.?keys key
                                                /* [↑]  add to key list if not in list.*/
        $.new.key= val                          /*assign a  value  to a  key for "new".*/
        if wordpos(key, $.new.?keys)==0  then $.new.?keys= $.new.?keys key
                                                /* [↑]  add to key list if not in list.*/
        @.wKey= max(@.wKey, length(key) )       /*find max width of a name of a  key.  */
        @.wVal= max(@.wVal, length(val) )       /*  "   "    "    " "   "   " "  value.*/
        @.wAA = max(@.wAAn, length(AAn) )       /*  "   "    "    " "   "   "    array.*/
        end   /*j*/
      return

/*──────────────────────────────────────────────────────────────────────────────────────*/ show: procedure expose $. @.; parse arg AAn; say; _= '═' /*set title char.*/

        do j=1  for words($.AAn.?keys)                                /*process keys.  */
        if j==1  then say  center('associate array', @.wAAn,     _)  ,
                           center("key"            , @.wKey,     _)  ,
                           center('value'          , @.wVal + 2, _)
        key= word($.AAn.?keys, j)                              /*get the name of a key.*/
        say center(AAn, @.wAAn)  right(key, @.wKey)  $.AAn.key /*show some information.*/
        end   /*j*/
      return</lang>
output   when using the internal default inputs:
═══associate array═══ ══key══ ═════value═════
        base             name Rocket Skates
        base            price 12.75
        base            color yellow

═══associate array═══ ══key══ ═════value═════
       update           price 15.25
       update           color red
       update            year 1974

═══associate array═══ ══key══ ═════value═════
         new             name Rocket Skates
         new            price 15.25
         new            color red
         new             year 1974

Ring

<lang ring> load "stdlib.ring"

list1 = [:name = "Rocket Skates", :price = 12.75, :color = "yellow"] list2 = [:price = 15.25, :color = "red", :year = 1974]

for n = 1 to len(list2)

   flag = 0
   for m = 1 to len(list1)
       if list2[n][1] = list1[m][1]
          flag = 1
          del(list1,m)
          add(list1,[list2[n][1],list2[n][2]])
          exit
       ok
   next
   if flag = 0
      add(list1,[list2[n][1],list2[n][2]])
   ok

next

for n = 1 to len(list1)

   see list1[n][1] + " = " + list1[n][2] + nl

next </lang> Output:

name = Rocket Skates
price = 15.25
color = red
year = 1974

Ruby

<lang ruby>base = {"name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"} update = {"price" => 15.25, "color" => "red", "year" => 1974}

result = base.merge(update) p result</lang>

Output:
{"name"=>"Rocket Skates", "price"=>15.25, "color"=>"red", "year"=>1974}

Rust

<lang rust>use std::collections::HashMap;

fn main() {

   let mut original = HashMap::new();
   original.insert("name", "Rocket Skates");
   original.insert("price", "12.75");
   original.insert("color", "yellow");
   let mut update = HashMap::new();
   update.insert("price", "15.25");
   update.insert("color", "red");
   update.insert("year", "1974");
   original.extend(&update);
   println!("{:#?}", original);

} </lang>

Output:
{
    "name": "Rocket Skates",
    "color": "red",
    "year": "1974",
    "price": "15.25",
}

SenseTalk

In addition to setting individual property values, SenseTalk includes 5 built-in operations for modifying property lists, to: add properties, replace properties, remove properties, retain properties, and rename properties. The operation to replace properties is needed for this task. <lang sensetalk>set base to {name:"Rocket Skates", price:12.75, color:"yellow"}

set update to {price:15.25, color:"red", year:1974}

put "Base data: " & base put "Update data: " & update

// replacing as an operator, to generate merged data on the fly: put "Merged data: " & base replacing properties in update

// replace as a command, to modify base data in place: replace properties of update in base put "Base after update: " & base </lang>

Output:
Base data: {color:"yellow", name:"Rocket Skates", price:12.75}
Update data: {color:"red", price:15.25, year:1974}
Merged data: {color:"red", name:"Rocket Skates", price:15.25, year:1974}
Base after update: {color:"red", name:"Rocket Skates", price:15.25, year:1974}

Smalltalk

<lang smalltalk>base := Dictionary withAssociations:{

        'name'-> 'Rocket Skates' .
        'price' -> 12.75 .
        'color' -> 'yellow' }.

update := Dictionary withAssociations:{

        'price' -> 15.25 .
        'color' -> 'red' .
        'year' -> 1974 }.

result := Dictionary new

            declareAllFrom:base;
            declareAllFrom:update.

Transcript showCR: result.</lang>

Output:
Dictionary(name->Rocket Skates price->15.25 year->1974 color->red)

Swift

Works with: Swift version 5+

<lang swift>let base : [String: Any] = ["name": "Rocket Skates", "price": 12.75, "color": "yellow"] let update : [String: Any] = ["price": 15.25, "color": "red", "year": 1974]

let result = base.merging(update) { (_, new) in new }

print(result)</lang>

Output:
["price": 15.25, "name": "Rocket Skates", "color": "red", "year": 1974]

Tcl

<lang tcl>set dict1 [dict create name "Rocket Skates" price 12.75 color yellow] set dict2 [dict create price 15.25 color red year 1974] dict for {key val} [dict merge $dict1 $dict2] {

   puts "$key: $val"

}</lang>

Output:
name: Rocket Skates
price: 15.25
color: red
year: 1974

VBA

3 ways to do this tasks : First : With Arrays + Type <lang vb> Private Type Associative

   Key As String
   Value As Variant

End Type Sub Main_Array_Associative() Dim BaseArray(2) As Associative, UpdateArray(2) As Associative

   FillArrays BaseArray, UpdateArray
   ReDim Result(UBound(BaseArray)) As Associative
   MergeArray Result, BaseArray, UpdateArray
   PrintOut Result

End Sub Private Sub MergeArray(Res() As Associative, Base() As Associative, Update() As Associative) Dim i As Long, Respons As Long

   Res = Base
   For i = LBound(Update) To UBound(Update)
       If Exist(Respons, Base, Update(i).Key) Then
           Res(Respons).Value = Update(i).Value
       Else
           ReDim Preserve Res(UBound(Res) + 1)
           Res(UBound(Res)).Key = Update(i).Key
           Res(UBound(Res)).Value = Update(i).Value
       End If
   Next

End Sub Private Function Exist(R As Long, B() As Associative, K As String) As Boolean Dim i As Long

   Do
       If B(i).Key = K Then
           Exist = True
           R = i
       End If
       i = i + 1
   Loop While i <= UBound(B) And Not Exist

End Function Private Sub FillArrays(B() As Associative, U() As Associative)

   B(0).Key = "name"
   B(0).Value = "Rocket Skates"
   B(1).Key = "price"
   B(1).Value = 12.75
   B(2).Key = "color"
   B(2).Value = "yellow"
   U(0).Key = "price"
   U(0).Value = 15.25
   U(1).Key = "color"
   U(1).Value = "red"
   U(2).Key = "year"
   U(2).Value = 1974

End Sub Private Sub PrintOut(A() As Associative) Dim i As Long

   Debug.Print "Key", "Value"
   For i = LBound(A) To UBound(A)
       Debug.Print A(i).Key, A(i).Value
   Next i
   Debug.Print "-----------------------------"

End Sub</lang>

Second way (simply) : with the Scripting Dictionary Object : <lang vb>Sub Main_With_Dictionary() Dim Base As Object, Update As Object, Merged As Object, K As Variant

   'INIT VARIABLE
   Set Base = CreateObject("Scripting.Dictionary")
   Set Update = CreateObject("Scripting.Dictionary")
   Set Merged = Base
   'FILL Base & Update
   Base.Add "name", "Rocket Skates"
   Base.Add "price", 12.75
   Base.Add "color", "yellow"
   Update.Add "price", 15.25
   Update.Add "color", "red"
   Update.Add "year", 1974
   'Fill Merge
   For Each K In Update.Keys
       Merged(K) = Update(K)
   Next
   'Print Out
   Debug.Print "Key", "Value"
   For Each K In Merged.Keys
       Debug.Print K, Merged(K)
   Next K

End Sub</lang>

And the Third : With a Class Module (named ClassArrayAssociative) The Class Module code: <lang vb>Option Explicit

Private mKey As String Private mValue As Variant

Public Property Get Value() As Variant

   Value = mValue

End Property Public Property Let Value(iValue As Variant)

   mValue = iValue

End Property Public Property Get Key() As Variant

   Key = mKey

End Property Private Property Let Key(iKey As Variant)

   mKey = iKey

End Property

Public Sub Add(K As String, V As Variant)

   Value = V
   Key = K

End Sub</lang> The Module code : <lang vb>Sub Main_With_Class() Dim Base(2) As New ClassArrayAssociative, Up(2) As New ClassArrayAssociative

   ReDim Result(UBound(Base)) As New ClassArrayAssociative
   'FILL Base & Update
   Base(0).Add "name", "Rocket Skates"
   Base(1).Add "price", 12.75
   Base(2).Add "color", "yellow"
   Result = Base
   Up(0).Add "price", 15.25
   Up(1).Add "color", "red"
   Up(2).Add "year", 1974
   'Update Result with Up
   Update Result, Up
   'Print Out
   Print_Out_2 Result

End Sub Private Sub Update(R() As ClassArrayAssociative, U() As ClassArrayAssociative) Dim i As Long, j As Long, Flag As Boolean

   For i = LBound(U) To UBound(U)
       j = LBound(R)
       Flag = False
       Do While j <= UBound(R) And Not Flag
           If R(j).Key = U(i).Key Then
               R(j).Value = U(i).Value
               Flag = True
           End If
           j = j + 1
       Loop
       If Not Flag Then
           ReDim Preserve R(UBound(R) + 1)
           Set R(UBound(R)) = New ClassArrayAssociative
           R(UBound(R)).Add U(i).Key, U(i).Value
       End If
   Next i

End Sub Private Sub Print_Out_2(A() As ClassArrayAssociative) Dim i As Long

   Debug.Print "Key", "Value"
   For i = LBound(A) To UBound(A)
       Debug.Print A(i).Key, A(i).Value
   Next i
   Debug.Print "-----------------------------"

End Sub</lang>

Output:
Key           Value
name          Rocket Skates
price          15,25 
color         red
year           1974 
-----------------------------


Wren

<lang ecmascript>var mergeMaps = Fn.new { |m1, m2|

   var m3 = {}
   for (key in m1.keys) m3[key] = m1[key]
   for (key in m2.keys) m3[key] = m2[key]
   return m3

}

var base = { "name": "Rocket Skates" , "price": 12.75, "color": "yellow" } var update = { "price": 15.25, "color": "red", "year": 1974 } var merged = mergeMaps.call(base, update) System.print(merged)</lang>

Output:
{name: Rocket Skates, color: red, price: 15.25, year: 1974}

zkl

<lang zkl>base:=Dictionary(

  "name", 	"Rocket Skates",
  "price", 	12.75,
  "color", 	"yellow",);

update:=Dictionary(

  "price", 	15.25,
  "color", 	"red",
  "year", 	1974,);

update.pump( new:=base.copy() );

new.pump(Void,fcn([(k,v)]){ println("%s\t%s".fmt(k,v)) });</lang>

Output:
price	15.25
color	red
year	1974
name	Rocket Skates