Associative array/Merging
Define two associative arrays, where one represents the following "base" data:

You are encouraged to solve this task according to the task description, using any language you may know.
- Task
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
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)- Output:
[color = red, name = Rocket Skates, price = 15.25, year = 1974]
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;
- 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
The associative array MODEs, operators etc. are contained in:
- File: aArray.a68 on Rosetta Code at ALGOL 68/prelude#aArray.a68
- File: aArrayBase.a68 on Rosetta Code at ALGOL 68/prelude#aArrayBase.a68
# associative array merging #
# the modes allowed as associative array element values - change to suit #
MODE AAVALUE = UNION( STRING, INT, REAL );
# the modes allowed as associative array element keys - change to suit #
MODE AAKEY = STRING;
# initial value for an array element #
AAVALUE init element value = "";
# include the associative array code #
PR read "aArrayBase.a68" PR
# 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 # ;
BEGIN # tests #
# 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;
# merge the arrays #
REF AARRAY c := INIT LOC AARRAY;
c UPDATE a UPDATE b;
# 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
END- Output:
name: Rocket Skates year: 1974 price: 15.25 color: red
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.
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
- Output:
{price:15.25, |color|:"red", |year|:1974, |name|:"Rocket Skates"}
(import std.Dict)
(let base (dict
"name" "Rocket Skates"
"price" "12.75"
"color" "yellow"))
(let update (dict
"price" "15.25"
"color" "red"
"year" "1974"))
(mut result (dict:copy base))
(dict:update! result update)
(print result)- Output:
{name: Rocket Skates, price: 15.25, color: red, year: 1974}
details: #[name: "Rocket Skates" price: 12.75 colour: 'yellow]
newDetails: extend details #[price: 15.25 colour: 'red year: 1974]
print newDetails
- Output:
[name:Rocket Skates price:15.25 colour:red year:1974]
merge(base, update){
Merged := {}
for k, v in base
Merged[k] := v
for k, v in update
Merged[k] := v
return Merged
}
Examples:
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
Outputs:
color : red name : Rocket Skates price : 15.25 year : 1974
# syntax: GAWK -f ASSOCIATIVE_ARRAY_MERGING.AWK
#
# sorting:
# PROCINFO["sorted_in"] is used by GAWK
# 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])
}
}
- 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
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)import ballerina/io;
function mergeMaps(map<any> m1, map<any> m2) returns map<any> {
map<any> m3 = {};
foreach string key in m1.keys() { m3[key] = m1.get(key); }
foreach string key in m2.keys() { m3[key] = m2.get(key); }
return m3;
}
public function main() {
map<any> base = { "name": "Rocket Skates" , "price": 12.75, "color": "yellow" };
map<any> update = { "price": 15.25, "color": "red", "year": 1974 };
map<any> merged = mergeMaps(base, update);
io:println(re `,`.replaceAll(merged.toString(), ", "));
}
- Output:
{"name":"Rocket Skates", "price":15.25, "color":"red", "year":1974}
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- 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
dim original(3, 2)
original[0, 0] = "name": original[0, 1] = "Rocket Skates"
original[1, 0] = "price": original[1, 1] = "12.75"
original[2, 0] = "color": original[2, 1] = "yellow"
dim update(3, 2)
update[0, 0] = "price": update[0, 1] = "15.25"
update[1, 0] = "color": update[1, 1] = "red"
update[2, 0] = "year": update[2, 1] = "1974"
dim merged(6, 2)
for i = 0 to 2
merged[i, 0] = update[i, 0]
merged[i, 1] = update[i, 1]
next i
index = 3
for i = 0 to 2
found = False
for j = 0 to 2
if original[i, 0] = update[j, 0] then
found = True
exit for
end if
next j
if not found then
merged[index, 0] = original[i, 0]
merged[index, 1] = original[i, 1]
index += 1
end if
next i
for i = 0 to index - 1
print "key: "; merged[i, 0]; ", value: "; merged[i, 1]
next i
- Output:
Same as FreeBASIC entry.
100 cls
110 dim original$(3,2)
120 original$(0,0) = "name"
130 original$(0,1) = "Rocket Skates"
140 original$(1,0) = "price"
150 original$(1,1) = "12.75"
160 original$(2,0) = "color"
170 original$(2,1) = "yellow"
180 dim update$(3,2)
190 update$(0,0) = "price"
200 update$(0,1) = "15.25"
210 update$(1,0) = "color"
220 update$(1,1) = "red"
230 update$(2,0) = "year"
240 update$(2,1) = "1974"
250 dim merged$(6,2)
270 for i = 0 to 2
280 merged$(i,0) = update$(i,0)
290 merged$(i,1) = update$(i,1)
300 next i
320 index = 3
330 for i = 0 to 2
340 found = 0
350 for j = 0 to 2
360 if original$(i,0) = update$(j,0) then
370 found = 1
380 goto 400
390 endif
400 next j
410 if found = 0 then
420 merged$(index,0) = original$(i,0)
430 merged$(index,1) = original$(i,1)
440 index = index+1
450 endif
460 next i
480 for i = 0 to index-1
490 print "key: ";merged$(i,0);", value: ";merged$(i,1)
500 next i
510 end
- Output:
Same as FreeBASIC entry.
Type Dictionary
As String key
As String value
End Type
Sub merge(original() As Dictionary, update() As Dictionary, result() As Dictionary)
Dim As Integer i, j, index
Dim As Boolean found
For i = 0 To Ubound(update)
result(i) = update(i)
Next i
index = i
For i = 0 To Ubound(original)
found = False
For j = 0 To Ubound(update)
If original(i).key = update(j).key Then
found = True
Exit For
End If
Next j
If Not found Then
result(index) = original(i)
index += 1
End If
Next i
End Sub
Dim As Dictionary original(2)
original(0).key = "name": original(0).value = "Rocket Skates"
original(1).key = "price": original(1).value = "12.75"
original(2).key = "color": original(2).value = "yellow"
Dim As Dictionary update(2)
update(0).key = "price": update(0).value = "15.25"
update(1).key = "color": update(1).value = "red"
update(2).key = "year": update(2).value = "1974"
Dim As Dictionary merged(Ubound(update) + Ubound(original) - 1)
merge(original(), update(), merged())
For i As Integer = 0 To Ubound(merged)
Print "key: "; merged(i).key; ", value: "; merged(i).value
Next i
Sleep
- Output:
key: price, value: 15.25 key: color, value: red key: year, value: 1974 key: name, value: Rocket Skates
100 CLS
110 DIM O$(3,2)
120 O$(0,0) = "name"
130 O$(0,1) = "Rocket Skates"
140 O$(1,0) = "price"
150 O$(1,1) = "12.75"
160 O$(2,0) = "color"
170 O$(2,1) = "yellow"
180 DIM U$(3,2)
190 U$(0,0) = "price"
200 U$(0,1) = "15.25"
210 U$(1,0) = "color"
220 U$(1,1) = "red"
230 U$(2,0) = "year"
240 U$(2,1) = "1974"
250 DIM M$(6,2)
270 FOR I = 0 TO 2
280 M$(I,0) = U$(I,0)
290 M$(I,1) = U$(I,1)
300 NEXT I
320 INDEX = 3
330 FOR I = 0 TO 2
340 FOUND = 0
350 FOR J = 0 TO 2
360 IF O$(I,0) = U$(J,0) THEN FOUND = 1 : GOTO 370
370 NEXT J
380 IF FOUND = 0 THEN M$(INDEX,0) = O$(I,0) : M$(INDEX,1) = O$(I,1) : INDEX = INDEX+1
390 NEXT I
410 FOR I = 0 TO INDEX-1
420 PRINT "key: ";M$(I,0);", value: ";M$(I,1)
430 NEXT I
440 END
The GW-BASIC solution works without any changes.
DECLARE SUB merge (original() AS ANY, update() AS ANY, result() AS ANY)
TYPE Dictionary
keyy AS STRING * 5
value AS STRING * 13
END TYPE
DIM original(2) AS Dictionary
original(0).keyy = "name": original(0).value = "Rocket Skates"
original(1).keyy = "price": original(1).value = "12.75"
original(2).keyy = "color": original(2).value = "yellow"
DIM update(2) AS Dictionary
update(0).keyy = "price": update(0).value = "15.25"
update(1).keyy = "color": update(1).value = "red"
update(2).keyy = "year": update(2).value = "1974"
DIM merged(UBOUND(update) + UBOUND(original) - 1) AS Dictionary
CALL merge(original(), update(), merged())
FOR i = 0 TO UBOUND(merged)
PRINT "keyy: "; merged(i).keyy; ", value: "; merged(i).value
NEXT i
END
SUB merge (original() AS Dictionary, update() AS Dictionary, result() AS Dictionary)
DIM i AS INTEGER, j AS INTEGER, index AS INTEGER, found AS INTEGER
FOR i = 0 TO UBOUND(update)
result(i) = update(i)
NEXT i
index = i
FOR i = 0 TO UBOUND(original)
found = 0
FOR j = 0 TO UBOUND(update)
IF original(i).keyy = update(j).keyy THEN
found = 1
EXIT FOR
END IF
NEXT j
IF found = 0 THEN
result(index) = original(i)
index = index + 1
END IF
NEXT i
END SUB
The QBasic solution works without any changes.
PROGRAM "Associative array/Merging"
VERSION "0.0000"
DECLARE FUNCTION Entry ()
FUNCTION Entry ()
DIM original$[3, 2]
original$[0, 0] = "name": original$[0, 1] = "Rocket Skates"
original$[1, 0] = "price": original$[1, 1] = "12.75"
original$[2, 0] = "color": original$[2, 1] = "yellow"
DIM update$[3, 2]
update$[0, 0] = "price": update$[0, 1] = "15.25"
update$[1, 0] = "color": update$[1, 1] = "red"
update$[2, 0] = "year": update$[2, 1] = "1974"
DIM merged$[6, 2]
FOR i = 0 TO 2
merged$[i, 0] = update$[i, 0]
merged$[i, 1] = update$[i, 1]
NEXT i
index = 3
FOR i = 0 TO 2
found = 0
FOR j = 0 TO 2
IF original$[i, 0] = update$[j, 0] THEN
found = 1
EXIT FOR
END IF
NEXT j
IF found = 0 THEN
merged$[index, 0] = original$[i, 0]
merged$[index, 1] = original$[i, 1]
INC index
END IF
NEXT i
FOR i = 0 TO index - 1
PRINT "key: "; merged$[i, 0]; ", value: "; merged$[i, 1]
NEXT i
END FUNCTION
END PROGRAM
- Output:
Same as FreeBASIC entry.
dim original$(3, 2)
original$(0, 0) = "name"
original$(0, 1) = "Rocket Skates"
original$(1, 0) = "price"
original$(1, 1) = "12.75"
original$(2, 0) = "color"
original$(2, 1) = "yellow"
dim update$(3, 2)
update$(0, 0) = "price"
update$(0, 1) = "15.25"
update$(1, 0) = "color"
update$(1, 1) = "red"
update$(2, 0) = "year"
update$(2, 1) = "1974"
dim merged$(6, 2)
for i = 0 to 2
merged$(i, 0) = update$(i, 0)
merged$(i, 1) = update$(i, 1)
next i
index = 3
for i = 0 to 2
found = 0
for j = 0 to 2
if original$(i, 0) = update$(j, 0) then
found = 1
break
end if
next j
if found = 0 then
merged$(index, 0) = original$(i, 0)
merged$(index, 1) = original$(i, 1)
index = index + 1
end if
next i
for i = 0 to index - 1
print "key: ", merged$(i, 0), ", value: ", merged$(i, 1)
next i
- Output:
Same as FreeBASIC entry.
#include <iostream>
#include <string>
#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;
}
- Output:
key: color, value: red key: name, value: Rocket Skates key: price, value: 15.25 key: year, value: 1974
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);
}
}
}
- Output:
[name, Rocket Skates] [price, 15.25] [color, red] [year, 1974]
(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"})
- Output:
{"name" "Rocket Skates", "price" "15.25", "color" "red", "year" "1974"}
With alists or plists
In Common Lisp, the value of a key in an alist or a plist is defined as the first value in the list with a matching key or indicator. Thus, all that is necessary to implement this algorithm for either is the following:
(append list2 list1)
These implementations for alists and plists are more complicated, but avoid duplicate keys in the results:
(defun merge-alists (alist1 alist2)
(nconc
(loop :for pair1 :in alist1
:for pair2 := (assoc (car pair1) alist2)
:do (setf alist2 (remove pair2 alist2))
:collect (or pair2 pair1))
alist2))
(defun merge-plists (plist1 plist2)
(let ((res '()))
(loop :for (key val) :on plist1 :by #'cddr
:do (setf (getf res key) val))
(loop :for (key val) :on plist2 :by #'cddr
:do (setf (getf res key) val))
res))
With hash tables
Common Lisp lacks several convenience functions to work with hash tables, so they have to be defined.
(defun merge-hash-tables (hashtable &rest other-hashtables)
(let ((result (make-hash-table :test (hash-table-test hashtable))))
(dolist (ht (list* hashtable other-hashtables))
(maphash #'(lambda (k v) (setf (gethash k result) v)) ht))
result))
;; aux functions
(defun make-hash-table-from-alist (alist &key (test 'equal))
(let ((result (make-hash-table :test test)))
(loop for (k . v) in alist
do (setf (gethash k result) v))
result))
(defun make-alist-from-hash-table (hashtable)
(let ((result ()))
(maphash #'(lambda (k v) (setf result (acons k v result))) hashtable)
(nreverse result)))
;; solving the task
(let ((base (make-hash-table-from-alist '(("name" . "Rocket Skates")
("price" . 12.75)
("color" . "yellow"))))
(update (make-hash-table-from-alist '(("price" . 15.25)
("color" . "red")
("year" . 1974)))))
(format t "base: ~a~%update: ~a~%merged: ~a~%"
(make-alist-from-hash-table base)
(make-alist-from-hash-table update)
(make-alist-from-hash-table (merge-hash-tables base update))))
- Output:
base: ((name . Rocket Skates) (price . 12.75) (color . yellow)) update: ((price . 15.25) (color . red) (year . 1974)) merged: ((name . Rocket Skates) (price . 15.25) (color . red) (year . 1974))
base = {"name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"}
update = { "price" => 15.25, "color" => "red", "year" => 1974 }
puts base.merge(update)
- Output:
{"name" => "Rocket Skates", "price" => 15.25, "color" => "red", "year" => 1974}
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}');
}
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.
- Output:
price 15,25 year 1974 color red name Rocket Skates
In the first part of this entry, we will focus on JSON objects as DuckDB has a function, json_merge_patch(), for merging them in accordance with the task description.
In the second and thirds part, we will define comparable functions for entities of type MAP (which do not require the keys to be strings) and of type STRUCT.
JSON
Given two JSON objects, base and update, the right-biased merge can be obtained simply by evaluating json_merge_patch(base,update).
Illustration
set variable base= { 'name': 'Rocket Skates', 'price': 12.75, 'color':'yellow'}::JSON;
set variable update = { 'price': 15.25, 'color': 'red', 'year': 1974 }::JSON;
select json_merge_patch(getvariable('base'),getvariable('update')) as add;
- Output:
┌──────────────────────────────────────────────────────────────────┐
│ add │
│ json │
├──────────────────────────────────────────────────────────────────┤
│ {"name":"Rocket Skates","price":15.25,"color":"red","year":1974} │
└──────────────────────────────────────────────────────────────────┘
MAPs
create or replace function map_merge_patch(a,b) as (
with keys_t as (
select (map_keys(a) + map_keys(b)).list_distinct() as keys
),
values_t as (
select list_transform(keys, key -> coalesce(b[key][1],a[key][1])) as values
from keys_t)
select MAP(keys, values) from keys_t, values_t
);
select map_merge_patch( MAP([1,2],[1,2]), MAP([1,3],[10,30])) as add;
- Output:
┌───────────────────────┐
│ add │
│ map(integer, integer) │
├───────────────────────┤
│ {3=30, 2=2, 1=10} │
└───────────────────────┘
STRUCTs
create or replace function struct_merge_patch(base, update) as (
<syntaxhighlight lang="sql">
with cte as (
from (select unnest(update))
positional join
(select COLUMNS(x -> x not in json_keys(update::JSON)) from (select unnest(base)))
)
select cte from cte
);
select struct_merge_patch( getvariable('base'), getvariable('update')) as merged;
- Output:
┌───────────────────────────────────────────────────────────────────────────┐
│ merged │
│ struct(price decimal(4,2), color varchar, "year" integer, "name" varchar) │
├───────────────────────────────────────────────────────────────────────────┤
│ {'price': 15.25, 'color': red, 'year': 1974, 'name': Rocket Skates} │
└───────────────────────────────────────────────────────────────────────────┘
base$[][] = [ [ "name" "Rocket Skates" ] [ "price" 12.75 ] [ "color" "yellow" ] ]
update$[][] = [ [ "price" 15.25 ] [ "color" "red" ] [ "year" 1974 ] ]
proc update &a$[][] &b$[][] .
for b to len b$[][]
for a to len a$[][]
if a$[a][1] = b$[b][1]
a$[a][2] = b$[b][2]
break 1
.
.
if a > len a$[][] : a$[][] &= b$[b][]
.
.
update base$[][] update$[][]
print base$[][]- Output:
[ [ "name" "Rocket Skates" ] [ "price" "15.25" ] [ "color" "red" ] [ "year" "1974" ] ]
Elixir has a built-in hashmap type, called Map.
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)
- 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:
base = %{"name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"}
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
- 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
The assoc-union word does this. assoc-union! is a variant that mutates the first associative array.
USING: assocs prettyprint ;
{ { "name" "Rocket Skates" } { "price" 12.75 } { "color" "yellow" } }
{ { "price" 15.25 } { "color" "red" } { "year" 1974 } }
assoc-union .
- Output:
V{
{ "name" "Rocket Skates" }
{ "price" 15.25 }
{ "color" "red" }
{ "year" 1974 }
}
module assoc_array_mod
implicit none
private
public :: KeyValue, merge_assoc_arrays
! Derived type for key-value pairs
type :: KeyValue
character(len=:), allocatable :: key
character(len=:), allocatable :: value
end type KeyValue
contains
! Function to merge two associative arrays
function merge_assoc_arrays(base, update) result(merged)
type(KeyValue), intent(in) :: base(:), update(:)
type(KeyValue), allocatable :: merged(:)
type(KeyValue), allocatable :: temp(:)
integer :: base_size, update_size, i, j, k, merged_size
logical :: key_exists
base_size = size(base)
update_size = size(update)
! Allocate temporary array to hold all possible keys (worst case: no overlap)
allocate(temp(base_size + update_size))
merged_size = 0
! Add all keys from update array (update takes precedence)
do i = 1, update_size
merged_size = merged_size + 1
temp(merged_size)%key = update(i)%key
temp(merged_size)%value = update(i)%value
end do
! Add keys from base array that are not in update
do i = 1, base_size
key_exists = .false.
do j = 1, update_size
if (base(i)%key == update(j)%key) then
key_exists = .true.
exit
end if
end do
if (.not. key_exists) then
merged_size = merged_size + 1
temp(merged_size)%key = base(i)%key
temp(merged_size)%value = base(i)%value
end if
end do
! Allocate merged array with exact size
allocate(merged(merged_size))
do i = 1, merged_size
merged(i)%key = temp(i)%key
merged(i)%value = temp(i)%value
end do
! Clean up temporary array
deallocate(temp)
end function merge_assoc_arrays
end module assoc_array_mod
program main
use assoc_array_mod
implicit none
type(KeyValue), allocatable :: base(:), update(:), merged(:)
integer :: i
! Initialize base associative array
allocate(base(3))
base(1) = KeyValue("name", "Rocket Skates")
base(2) = KeyValue("price", "12.75")
base(3) = KeyValue("color", "yellow")
! Initialize update associative array
allocate(update(3))
update(1) = KeyValue("price", "15.25")
update(2) = KeyValue("color", "red")
update(3) = KeyValue("year", "1974")
! Merge the arrays
merged = merge_assoc_arrays(base, update)
! Print the merged array
print *, "Merged associative array:"
do i = 1, size(merged)
print *, "Key: ", merged(i)%key, ", Value: ", merged(i)%value
end do
! Clean up
deallocate(base, update, merged)
end program main
- Output:
Merged associative array: Key: price, Value: 15.25 Key: color, Value: red Key: year, Value: 1974 Key: name, Value: Rocket Skates
void local fn DoIt
CFDictionaryRef base = @{@"name" :@"Rocket Skates", @"price":@12.75, @"color":@"yellow"}
CFDictionaryRef update = @{@"price":@15.25, @"color":@"red", @"year":@1974}
CFMutableDictionaryRef merged = fn MutableDictionaryWithDictionary( base )
MutableDictionaryAddEntriesFromDictionary( merged, update )
print merged
end fn
fn DoIt
HandleEventsThis option uses FB's 'concat' function
void local fn Doit
CFDictionaryRef base = @{ @"name":@"Rocket Skates", @"price":@12.75 }
CFDictionaryRef update = @{ @"price":@15.25, @"color":@"red", @"year":@1974 }
CFDictionaryRef result = concat( base, update )
print result
end fn
fn DoIt
HandleEvents- Output:
{
color = red;
name = "Rocket Skates";
price = "15.25";
year = 1974;
}
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)
}
- Output:
map[color:red name:Rocket Skates price:15.25 year:1974]
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:
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))
- Output:
Item {name = Just "Rocket Skates", price = Just 15.25, color = Just "red", year = Just 1974}
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
- Output:
prompt$ unicon -s merge.icn -x color = red name = Rocket Skates price = 15.25 year = 1974
merge=: ,. NB. use: update merge original
compress=: #"1~ ~:@:keys
keys=: {.
values=: {:
get=: [: > ((i.~ keys)~ <)~ { values@:] NB. key get (associative array)
pair=: [: |: <;._2;._2
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
See also, Java - Associative array/Creation.
This task illustrates the difference between statically typed languages, and dynamically typed.
With exception to the var keyword, Java is statically typed.
So, using an undefined, non-static, value, creates a trivial situation.
A good way to understand this task is that it's not possible in a static-typed language.
It defeats the purpose of defining the data-type.
For Java, if you're going to use Object as your data-type, you need to re-evaluate the method of abstraction.
Java offers generics, interfaces, and abstract classes for this task.
Considering this, to complete this specific task, I would just store the values as strings.
import java.util.LinkedHashMap;
import java.util.Map;
Map<String, String> mapA = new LinkedHashMap<>();
mapA.put("name", "Rocket Skates");
mapA.put("price", "12.75");
mapA.put("color", "yellow");
Map<String, String> mapB = new LinkedHashMap<>();
mapB.put("price", "15.25");
mapB.put("color", "red");
mapB.put("year", "1974");
Map<String, String> mapC = new LinkedHashMap<>();
mapC.putAll(mapA);
mapC.putAll(mapB);
To show that the original maps are not affected.
for(Map.Entry<String, String> entry : mapA.entrySet())
System.out.printf("%-20s%s%n", entry.getKey(), entry.getValue());
for(Map.Entry<String, String> entry : mapB.entrySet())
System.out.printf("%-20s%s%n", entry.getKey(), entry.getValue());
for(Map.Entry<String, String> entry : mapC.entrySet())
System.out.printf("%-20s%s%n", entry.getKey(), entry.getValue());
name Rocket Skates price 12.75 color yellow
price 15.25 color red year 1974
name Rocket Skates price 15.25 color red year 1974
While not recommended, due to scalability, if you did want to use an Object as the value, you could use the following implementation.
This will produce the same output as above.
Map<String, Object> mapA = new LinkedHashMap<>();
mapA.put("name", "Rocket Skates");
mapA.put("price", 12.75);
mapA.put("color", "yellow");
Map<String, Object> mapB = new LinkedHashMap<>();
mapB.put("price", 15.25);
mapB.put("color", "red");
mapB.put("year", 1974);
Map<String, Object> mapC = new LinkedHashMap<>();
mapC.putAll(mapA);
mapC.putAll(mapB);
const base = {
"name": "Rocket Skates",
"price": 12.75,
"color": "yellow"
};
const update = {
"price": 15.25,
"color": "red",
"year": 1974
};
// While ES6 destructuring may be cleaner, using Object.assign (provided in the original answer) instead is about 15-20% faster.
// source: https://jsbench.me/jom7uh9o1t/1
const final = Object.assign(base, update);
// Using ES6 destructuring method: const final = { ...base, ...update };
console.log(JSON.stringify(final, null, 4));
- Output:
{
"name": "Rocket Skates",
"price": 15.25,
"color": "red",
"year": 1974
}
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> 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"
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")
}
- 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}
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
- Output:
price: 15.25 color: red year: 1974 name: Rocket Skates
module mergeList {
a=list:="name":="Rocket Skates", "price":=12.75, "color":="yellow"
b=list:="price":=15.25, "color":="red", "year":=1974
c=list
bb=each(a)
while bb {
append c, eval$(bb!):=eval(bb)
}
bb=each(b)
while bb {
if exist(c, eval$(bb!)) then
return c, eval$(bb!):=eval(bb)
else
append c, eval$(bb!):=eval(bb)
end if
}
bb=each(c)
Print format$(" |{0:8}|{1}", "Key", "Value")
Gosub simple
while bb {
fun1(bb^+1, eval$(bb!),eval(bb))
}
Gosub simple
sub fun1(n, a as string, b as variant)
local string c=if$(type$(b)="String"->quote$(b), ""+b)
Print format$("{0::-2}|{1:-8}|{2:15}|", n, quote$(a), c)
end sub
simple:
Print "--+--------+---------------+"
Return
}
mergeList
- Output:
|Key |Value --+--------+---------------+ 1| "name"|"Rocket Skates"| 2| "price"|15.25 | 3| "color"|"red" | 4| "year"|1974 | --+--------+---------------+
a1 = <|"name" -> "Rocket Skates", "price" -> 12.75, "color" -> "yellow"|>;
a2 = <|"price" -> 15.25, "color" -> "red", "year" -> 1974|>;
Merge[{a1, a2}, Last]
- Output:
<|"name" -> "Rocket Skates", "price" -> 15.25, "color" -> "red", "year" -> 1974|>
MiniScript supports merging maps with the + operator.
base = {"name":"Rocket Skates", "price":12.75, "color":"yellow"}
update = {"price":15.25, "color":"red", "year":1974}
result = base + update
print result
- Output:
{"color": "red", "name": "Rocket Skates", "price": 15.25, "year": 1974}
Let's use simple association lists.
(setq data1 '("name" "Rocket Skates"
"price" 12.75
"color" "yellow"))
(setq data2 '("price" 15.25
"color" "red"
"year" 1974))
(define (list->alist lst) (explode lst 2))
(macro (aset! Alist Key Val)
(local (E-Message)
(unless
(catch
(setf (assoc Key Alist) (list ($it 0) Val))
'E-Message)
(setf Alist (cons (list Key Val) Alist)))))
(define (foo list1 list2)
(let (out (list->alist list1))
(dolist (a (list->alist list2))
(aset! out (a 0) (string (a 1))))
(println out "\n")
(dolist (a out)
(println (format "%-5s %s" a)))))
(foo data1 data2)
- Output:
(("year" "1974") ("name" "Rocket Skates") ("price" "15.25") ("color" "red"))
year 1974
name Rocket Skates
price 15.25
color red
Let's make it more interesting. The "color" field will be a list of colors; the color from the new array will be appended to what's already in the field.
Also, the price in the second associative array will be added to the original price.
(setq data1 '("name" "Rocket Skates"
"price" 12.75
"color" "yellow"))
(setq data2 '("price" 3.20
"color" "red"
"year" 1974))
(macro (ainc! Alist Key Val Func)
(local (E-Message)
(unless Func (set 'Func +))
(unless
(catch
(setf (assoc Key Alist)
(list ($it 0) (Func (or Val 1) ($it 1))))
'E-Message)
(setf Alist (cons (list Key (or Val 1)) Alist)))))
(define (list->alist xs)
(collect
(and (true? xs)
(if (= "color" (xs 0))
(list (pop xs) (list (pop xs)))
(list (pop xs) (pop xs))))))
(define (bu) (bind (apply unify $args)))
(define (foo list1 list2 , K V)
(let (out (list->alist list1))
(dolist (a (list->alist list2))
(bu '(K V) a)
(case K
("price" (ainc! out K V add))
("color" (ainc! out K V append))
;; ainc! can even be used to make a new entry or replace old value.
(true (ainc! out K V or))))
(println out "\n")
(dolist (a out)
(bu '(K V) a)
(println (format "%-5s " K) V))))
(foo data1 data2)
- Output:
(("year" 1974) ("name" "Rocket Skates") ("price" 15.95)
("color" ("red" "yellow")))
year 1974
name Rocket Skates
price 15.95
color ("red" "yellow")
#!/usr/bin/env nr
/* NetRexx */
options replace java comments format
-- . ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5
-- key names
parse 'name price colour year' name price colour year .
base = ''
base[name] = 'Rocket Skate'
base[price] = 12.75
base[colour] = 'yellow'
base[0] = 'name price colour'
update = ''
update[price] = 15.25
update[colour] = 'red'
update[year] = 1974
update[0] = 'price colour year'
merged = ''
merged[0] = ''
-- add 'base' into 'merged'
merged.copyindexed(base)
-- merge updates from 'update'
merged.copyindexed(update)
-- collect keynames in key 0
loop base[0].words() to 1 by -1
key = base[0].word(k_)
if merged[0].wordpos(key) = 0 then
merged[0] = key merged[0]
end k_
say 'Original contents of ''base'''
showContents(base)
say 'Contents of ''updates'''
showContents(update)
say 'Contents of ''merged'' contains:'
showContents(merged)
return
-- . ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5
method showContents(base) private static
loop k_ = 1 to base[0].words()
key = base[0].word(k_)
say key.right(7) ':' base[key]
end k_
say
return
- Output:
Original contents of 'base' name : Rocket Skate price : 12.75 colour : yellow Contents of 'updates' price : 15.25 colour : red year : 1974 Contents of 'merged' contains: name : Rocket Skate price : 15.25 colour : red year : 1974
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
- Output:
{"name": "Rocket Skates", "year": "1974", "color": "red", "price": "15.25"}
const base = {name: 'Rocket Skates' price: 12.75 color: 'yellow'}
const update = {price: 15.25 color: 'red' year: 1974}
$base | merge $update- Output:
╭───────┬───────────────╮ │ name │ Rocket Skates │ │ price │ 15.25 │ │ color │ red │ │ year │ 1974 │ ╰───────┴───────────────╯
#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;
}
- Output:
{
color = red;
name = "Rocket Skates";
price = "15.25";
year = 1974;
}
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:
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)
;;
Association list : naive and functional approach.
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 ;;
Binary tree/Map functor : proper functional approach.
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' ;;
Hash table : imperative/mutable approach.
(* 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 ;;
Since version 3.1.1 function `ff-union` changed from `(ff-union a1 a2 collide)` to `(ff-union collide a1 a2 ...)`!
(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 collide a1 a2))
- 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))
begin
var base := Dict(('name','Rocket Skates'),
('price','12.75'),
('color','yellow'));
var update := Dict(('price','15.25'),
('color','red'),
('year','1974'));
var merged := new Dictionary<string,string>;
foreach var kv in base.Concat(update) do
merged[kv.Key] := kv.Value;
merged.PrintLines
end.
- Output:
(name,Rocket Skates) (price,15.25) (color,red) (year,1974)
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;
- 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
with javascript_semantics 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)
- Output:
{{"color","red"},{"name","Rocket Skates"},{"price",15.25},{"year",1974}}
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<?
$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);
?>
- Output:
Array
(
[price] => 15.25
[color] => red
[year] => 1974
[name] => Rocket Skates
)
Alternative:
<?
$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);
?>
- Output:
Array
(
[name] => Rocket Skates
[price] => 15.25
[color] => red
[year] => 1974
)
local function merge_maps(m1, m2)
local m3 = {}
for m1:keys() as key do m3[key] = m1[key] end
for m2:keys() as key do m3[key] = m2[key] end
return m3
end
local base = {name = "Rocket Skates", price = 12.75, color = "yellow"}
local update = {price = 15.25, color = "red", year = 1974}
local merged = merge_maps(base, update)
for k, v in merged do print(k, v) end
- Output:
Note that order is not guaranteed and may differ between runs.
name Rocket Skates year 1974 price 15.25 color red
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
- Output:
price : 15.25 color : red year : 1974 name : Rocket Skates
As of Python 3.5, this can be solved with the dictionary unpacking operator.
base = {"name":"Rocket Skates", "price":12.75, "color":"yellow"}
update = {"price":15.25, "color":"red", "year":1974}
result = {**base, **update}
print(result)
- Output:
{'name': 'Rocket Skates', 'price': 15.25, 'color': 'red', 'year': 1974}
- Alternative
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)
- Output:
{'name': 'Rocket Skates', 'price': 15.25, 'color': 'red', 'year': 1974}
- New alternative using '|'
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/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)))
- Output:
'#hash(("color" . "red") ("name" . "Rocket Skates") ("price" . 15.25) ("year" . 1974))
(formerly Perl 6)
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.
# Show original hashes
say my %base = :name('Rocket Skates'), :price<12.75>, :color<yellow>;
say my %update = :price<15.25>, :color<red>, :year<1974>;
# Need to assign to anonymous hash to get the desired results and avoid mutating
# TIMTOWTDI
say "\nUpdate:\n", join "\n", sort %=%base, %update;
# Same
say "\nUpdate:\n", {%base, %update}.sort.join: "\n";
say "\nMerge:\n", join "\n", sort ((%=%base).push: %update)».join: ', ';
# Same
say "\nMerge:\n", ({%base}.push: %update)».join(', ').sort.join: "\n";
# Demonstrate unmutated hashes
say "\n", %base, "\n", %update;
- 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}
Include How to use
Include Source code
The Classic 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. Therefore you must track the keys yourself in a so-called 'index table'. That might be an array itself, or a list. Here I choose a list.
Below program has basic routines for processing the arrays (ProcXxxx). They are very elementary, only 'append' and 'update'. The routines ShowXxxx display the arrays.
-- 21 Feb 2026
include Setting
say 'ASSOCIATIVE ARRAY: MERGE'
say version
say
call CreateBase
call ShowBase 'Original'
call CreateUpdate
call ShowUpdate
call MergeBaseUpdate
call ShowBase 'Merged'
call Showvars
exit
CreateBase:
base=''; base.=''
call ProcBase 'name','Rocket Skates'
call ProcBase 'price',12.75
call ProcBase 'color','Yellow'
return
ShowBase:
parse arg xx
sep=Copies('-',20)
say 'Base array' xx
say sep
say 'Key value'
say sep
do i = 1 to Words(base)
key=Word(base,i)
say Left(key,6) base.key
end
say sep
say
return
CreateUpdate:
upda=''; upda.=''
call ProcUpdate 'price',15.25
call ProcUpdate 'color','Red'
call ProcUpdate 'year',1974
return
ShowUpdate:
say 'Update array'
say sep
say 'Key value'
say sep
do i = 1 to Words(upda)
key=Word(upda,i)
say Left(key,6) upda.key
end
say sep
say
return
MergeBaseUpdate:
do w = 1 to Words(upda)
key=Word(upda,w); val=upda.key
call ProcBase key,val
end
return
ProcBase:
parse arg k,v
if WordPos(k,base) = 0 then
base=base k
base.k=v
return
ProcUpdate:
parse arg k,v
if WordPos(k,upda) = 0 then
upda=upda k
upda.k=v
return
-- Showvars
include Math
- Output:
ASSOCIATIVE ARRAY: MERGE REXX-Regina_3.9.7(MT) 5.00 18 Mar 2025 Base array Original -------------------- Key value -------------------- name Rocket Skates price 12.75 color Yellow -------------------- Update array -------------------- Key value -------------------- price 15.25 color Red year 1974 -------------------- Base array Merged -------------------- Key value -------------------- name Rocket Skates price 15.25 color Red year 1974 -------------------- VARIABLE POOL Name=BASE, Value=" name price color year" Name=BASE., Value="" Name=BASE.color, Value="Red" Name=BASE.name, Value="Rocket Skates" Name=BASE.price, Value="15.25" Name=BASE.year, Value="1974" Name=COMMAND, Value="COMMAND" Name=DISP!, Value="1" Name=FILE!, Value="Variables.txt" Name=GLOB., Value="" Name=GLOB.ELAPS, Value="11:35:13.490000" Name=GLOB.MAXTIME, Value="60" Name=GLOB.MINTIME, Value="1" Name=GLOB.OOREXX, Value="0" Name=GLOB.REGINA, Value="1" Name=GLOB.TIMER, Value="11:35:13.490000" Name=I, Value="5" Name=K, Value="year" Name=KEY, Value="year" Name=MEMO., Value="" Name=PROGRAM, Value="C:\Rex\Rosetta\A\Runner.rex" Name=RC, Value="0" Name=RUN!, Value="assocmerge.rex" Name=SEP, Value="--------------------" Name=SIGL, Value="33" Name=SYSTEM!, Value="WIN64" Name=SYSTEM, Value="WIN64" Name=TEXT!, Value="" Name=UPDA, Value=" price color year" Name=UPDA., Value="" Name=UPDA.color, Value="Red" Name=UPDA.price, Value="15.25" Name=UPDA.year, Value="1974" Name=V, Value="1974" Name=VAL, Value="1974" Name=VERSION, Value="REXX-Regina_3.9.7(MT) 5.00 18 Mar 2025" Name=W, Value="4" Name=XX, Value="Merged"
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
nextOutput:
name = Rocket Skates price = 15.25 color = red year = 1974
base = {"name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"}
update = {"price" => 15.25, "color" => "red", "year" => 1974}
result = base.merge(update)
p result
- Output:
{"name"=>"Rocket Skates", "price"=>15.25, "color"=>"red", "year"=>1974}
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);
}
- Output:
{
"name": "Rocket Skates",
"color": "red",
"year": "1974",
"price": "15.25",
}
Quick and Dirty
The procedures which access association lists (alist) in Scheme prefer the first matched item
in an alist. Hence, a merge may be implemented by simply appending the update alist to the
front of the base alist. The downside is this leaves a bunch of useless junk in the alist.
; Merge alists by appending the update list onto the front of the base list.
; (The extra '() is so that append doesn't co-opt the second list.)
(define append-alists
(lambda (base update)
(append update base '())))
; Test...
(printf "~%Merge using append procedure...~%")
; The original base and update alists.
(let ((base '(("name" . "Rocket Skates") ("price" . 12.75) ("color" . "yellow" )))
(update '(("price" . 15.25) ("color" . "red") ("year" . 1974))))
; Merge by appending the update list onto the front of the base list.
(let ((merged (append-alists base update)))
; Show that everything worked.
(printf "Merged alist:~%~s~%" merged)
(printf "Values from merged alist:~%")
(let loop ((keys '("name" "price" "color" "year")))
(unless (null? keys)
(printf "~s -> ~s~%" (car keys) (cdr (assoc (car keys) merged)))
(loop (cdr keys))))))
- Output:
Merge using append procedure...
Merged alist:
(("price" . 15.25) ("color" . "red") ("year" . 1974) ("name" . "Rocket Skates") ("price" . 12.75) ("color" . "yellow"))
Values from merged alist:
"name" -> "Rocket Skates"
"price" -> 15.25
"color" -> "red"
"year" -> 1974
More True to Intent
This is more true to the intent of the Task. It generates a new alist with only the key/value
pairs needed.
; Merge the given alists. Prefer the items from the "update" alist.
; Returns a new list; the argument lists are not modified.
(define merge-alists
(lambda (base update)
(let ((merged (list-copy update))
(remains (list-copy base)))
(let loop ((shadowing merged))
(if (null? shadowing)
(append merged remains)
(begin (set! remains (remp (lambda (pair) (equal? (car pair) (caar shadowing)))
remains))
(loop (cdr shadowing))))))))
; Test...
(printf "~%Merge using defined merge-alists procedure...~%")
; The original base and update alists.
(let ((base '(("name" . "Rocket Skates") ("price" . 12.75) ("color" . "yellow" )))
(update '(("price" . 15.25) ("color" . "red") ("year" . 1974))))
; Merge using the defined merge-alists procedure.
(let ((merged (merge-alists base update)))
; Show that everything worked.
(printf "Merged alist:~%~s~%" merged)
(printf "Values from merged alist:~%")
(let loop ((keys '("name" "price" "color" "year")))
(unless (null? keys)
(printf "~s -> ~s~%" (car keys) (cdr (assoc (car keys) merged)))
(loop (cdr keys))))))
- Output:
Merge using defined merge-alists procedure...
Merged alist:
(("price" . 15.25) ("color" . "red") ("year" . 1974) ("name" . "Rocket Skates"))
Values from merged alist:
"name" -> "Rocket Skates"
"price" -> 15.25
"color" -> "red"
"year" -> 1974
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.
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- 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}
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.
- Output:
Dictionary(name->Rocket Skates price->15.25 year->1974 color->red)
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)
- Output:
["price": 15.25, "name": "Rocket Skates", "color": "red", "year": 1974]
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"
}
- Output:
name: Rocket Skates price: 15.25 color: red year: 1974
Tcl arrays are associative arrays consisting of a list of {item value} pairs. The language creates individual variables of the form array(field) containing a value. To set array values:
set arrayname(item) $value
# or set a series of item value pairs at one time:
# create initial array
array set skates {
name {Rocket Skates}
price 12.75
color yellow
}
Tcl cannot pass arrays into and out of procedures directly. (that is an advantage of Tcl 8.5's dict), but you can get around it by converting it to and from a list with the [array get <arrayname>] command.
# print formatted output
proc print_array {fields arr} {
# list back to array
array set A $arr
set names [array names A]
foreach key $fields {
# format output
puts -nonewline stdout [format "%-10s" $key]
if {$key in $names} {
puts stdout [format "%-16s" $A($key)]
} else {
puts stdout ""
}
}
}
# set field order
set fields [list name price color year]
puts "skates"
print_array $fields [array get skates]
# list of updates {arrayname item value}
set updates {
{skates price 15.15}
{skates color red}
{skates year 1974}
}
# update array
foreach update $updates {
lassign $update item field value
array set $item [list $field $value]
}
puts [string repeat "-" 24]
puts "skates updated"
print_array $fields [array get skates]
- Output:
skates name Rocket Skates price 12.75 color yellow year ------------------------ skates updated name Rocket Skates price 15.15 color red year 1974
This is almost certainly not the optimal or most idiomatic solution, but hey it works!
Base ← map {"name" "price" "color"} {"Rocket Skates" 12.75 "yellow"}
Update ← map {"price" "color" "year"} {15.25 "red" 1974}
&pBase
&pUpdate
UnmapAndPop ← ◌: °map
GetAndMap ← ˜map˜get
°⊂ UnmapAndPop Base UnmapAndPop Update
Base.
GetAndMap
.:◌:
Update
GetAndMap
&p"\n"
&p⊂
&p"\n"
&pBase
&pUpdate- Output:
{"name"→"Rocket Skates" "price"→12.75 "color"→"yellow"}
{"price"→15.25 "color"→"red" "year"→1974}
{"price"→15.25 "color"→"red" "year"→1974 "name"→"Rocket Skates"}
{"name"→"Rocket Skates" "price"→12.75 "color"→"yellow"}
{"price"→15.25 "color"→"red" "year"→1974}
3 ways to do this tasks : First : With Arrays + Type
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
Second way (simply) : with the Scripting Dictionary Object :
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
And the Third : With a Class Module (named ClassArrayAssociative) The Class Module code:
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
The Module code :
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
- Output:
Key Value name Rocket Skates price 15,25 color red year 1974 -----------------------------
set d1=createobject("Scripting.Dictionary")
d1.add "name", "Rocket Skates"
d1.add "price", 12.75
d1.add "color", "yellow"
set d2=createobject("Scripting.Dictionary")
d2.add "price", 15.25
d2.add "color", "red"
d2.add "year", 1974
set d3=createobject("Scripting.Dictionary")
for each k1 in d1.keys
if not d3.exists(k1) then
d3.add k1, d1(k1)
else
d3(k1)=d1(k1)
end if
next
for each k2 in d2.keys
if not d3.exists(k2) then
d3.add k2, d2(k2)
else
d3(k2)=d2(k2)
end if
next
for each k3 in d3.keys
wscript.echo k3 & vbtab & d3(k3)
next
- Output:
name Rocket Skates price 15.25 color red year 1974
type Generic = int|string|f64
type Assoc = map[string]Generic
fn merge(base Assoc, update Assoc) Assoc {
mut result := Assoc(map[string]Generic{})
for k, v in base {
result[k] = v
}
for k, v in update {
result[k] = v
}
return result
}
fn main() {
base := Assoc({"name": Generic("Rocket Skates"), "price": 12.75, "color": "yellow"})
update := Assoc({"price": Generic(15.25), "color": "red", "year": 1974})
result := merge(base, update)
for k,v in result {
println('$k: $v')
}
}- Output:
name: Generic('Rocket Skates')
price: Generic(15.25)
color: Generic('red')
year: Generic(1974)
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)
- Output:
{name: Rocket Skates, color: red, price: 15.25, year: 1974}
!ys-0
# Merge two maps: the result has every key from either, with the
# update map's value winning on conflicts. `merge` does exactly this,
# taking values from later maps when keys collide.
defn main():
base =:: {name: Rocket Skates, price: 12.75, color: yellow}
update =:: {price: 15.25, color: red, year: 1974}
merged =: merge(base update)
each k merged:keys:
say: "$k: $(merged.$k)"
- Output:
$ ys associative-array-merging.ys name: Rocket Skates price: 15.25 color: red year: 1974
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)) });- Output:
price 15.25 color red year 1974 name Rocket Skates