Associative array/Merging: Difference between revisions
→{{header|Python}}: Used more explicit base.copy() instead of dict(base) |
m indented tables to be more centered. |
||
Line 4: | Line 4: | ||
Define two associative arrays, where one represents the following "base" data: |
Define two associative arrays, where one represents the following "base" data: |
||
{| class="wikitable" |
::::: {| class="wikitable" |
||
|+ |
|+ |
||
| '''Key''' || '''Value''' |
| '''Key''' || '''Value''' |
||
Line 17: | Line 17: | ||
And the other represents "update" data: |
And the other represents "update" data: |
||
{| class="wikitable" |
::::: {| class="wikitable" |
||
|+ |
|+ |
||
| '''Key''' || '''Value''' |
| '''Key''' || '''Value''' |
||
Line 30: | Line 30: | ||
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: |
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: |
||
{| class="wikitable" |
::::: {| class="wikitable" |
||
|+ |
|+ |
||
| '''Key''' || '''Value''' |
| '''Key''' || '''Value''' |
||
Line 42: | Line 42: | ||
| "year" || 1974 |
| "year" || 1974 |
||
|} |
|} |
||
<br><br> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
Revision as of 13:19, 15 January 2020
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
Factor
The assoc-union
word does this. assoc-union!
is a variant that mutates the first associative array.
<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}
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 }
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"
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
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}
Objective-C
<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; }
Perl
<lang perl>my %base = ("name" => "Rocket Skates", "price" => 12.75, "color" => "yellow"); my %update = ("price" => 15.25, "color" => "red", "year" => 1974);
my %result = (%base, %update);
while (($k,$v) = each %result) {
print "$k => $v\n";
}</lang>
- Output:
name => Rocket Skates price => 15.25 color => red year => 1974
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 Perl 6.
<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>;
- 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;</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}
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 )
Python
As of Python 3.5, this can be solved with the dictionary unpacking operator.
<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}
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.
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. <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
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}
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