Here's where you went wrong:
Map<Opportunity> salesParticipants = new Map<Opportunity>();
Maps need to have two data types, one for the Key, and one for the Value.
Map<Id, Opportunity> salesParticipants = new Map<Id, Opportunity>();
It seems to me you're confusing List/Set and Map, since you're also trying to use "add"; the Map type uses "put" instead.
Finally, it seems that you're really just trying to map one Id to another, so you probably meant:
Map<Id, Id> salesParticipants = new Map<Id, Id>();
for(Opportunity oppy : newMap.values()) {
if(oppy.Sales_Participant_1__c != null && oldMap.get(oppy.Id).Sales_Participant_1__c != oppy.Sales_Participant_1__c) {
salesParticipants.put(oppy.Id, oppy.Sales_Participant_1__c);
}
}
Answer from sfdcfox on Stack ExchangeHere's where you went wrong:
Map<Opportunity> salesParticipants = new Map<Opportunity>();
Maps need to have two data types, one for the Key, and one for the Value.
Map<Id, Opportunity> salesParticipants = new Map<Id, Opportunity>();
It seems to me you're confusing List/Set and Map, since you're also trying to use "add"; the Map type uses "put" instead.
Finally, it seems that you're really just trying to map one Id to another, so you probably meant:
Map<Id, Id> salesParticipants = new Map<Id, Id>();
for(Opportunity oppy : newMap.values()) {
if(oppy.Sales_Participant_1__c != null && oldMap.get(oppy.Id).Sales_Participant_1__c != oppy.Sales_Participant_1__c) {
salesParticipants.put(oppy.Id, oppy.Sales_Participant_1__c);
}
}
Take a look at the Apex Developer Guide on Maps:
Maps
A map is a collection of key-value pairs where each unique key maps to a single value. Keys and values can be any data type—primitive types, collections, sObjects, user-defined types, and built-in Apex types. For example, the following table represents a map of countries and currencies:
Country (Key) 'United States' 'Japan' 'France' 'England' 'India' Currency (Value) 'Dollar' 'Yen' 'Euro' 'Pound' 'Rupee'Map keys and values can contain any collection, and can contain nested collections. For example, you can have a map of Integers to maps, which, in turn, map Strings to lists. Map keys can contain up to only four levels of nested collections.
To declare a map, use the Map keyword followed by the data types of the key and the value within
<>characters. For example:Map<String, String> country_currencies = new Map<String, String>(); Map<ID, Set<String>> m = new Map<ID, Set<String>>();
If you look at these, and examine the Maps in your method signature, you will see that there should be two types separated by a comma within your angle brackets (<>). You could denote the correct way to write a Map type as Map<T1, T2>, where T1 is the key type and T2 is the value type. That can be a Map<String, String>, Map<Id, Opportunity>, etc. In your declaration, you only have one type specified. There is no such thing as a Map<Opportunity>, because either you didn't specify the key type or you didn't specify the value type.
One option is a list comprehension:
[add(x, 2) for x in [1, 2, 3]]
More options:
a = [1, 2, 3]
import functools
map(functools.partial(add, y=2), a)
import itertools
map(add, a, itertools.repeat(2, len(a)))
The docs explicitly suggest this is the main use for itertools.repeat:
Make an iterator that returns object over and over again. Runs indefinitely unless the times argument is specified. Used as argument to
map()for invariant parameters to the called function. Also used withzip()to create an invariant part of a tuple record.
And there's no reason for pass len([1,2,3]) as the times argument; map stops as soon as the first iterable is consumed, so an infinite iterable is perfectly fine:
>>> from operator import add
>>> from itertools import repeat
>>> list(map(add, [1,2,3], repeat(4)))
[5, 6, 7]
In fact, this is equivalent to the example for repeat in the docs:
>>> list(map(pow, range(10), repeat(2)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
This makes for a nice lazy-functional-language-y solution that's also perfectly readable in Python-iterator terms.
It would be best to provide expected output explicitly, but I think I understand, and maybe something like this would work. I've created a dummy function just for explicitness:
fn[_] := Array[x, {2, 2}];
Append @@@ Comap[{fn, Max}] /@ testlist
(* {{{x[1, 1], x[1, 2]}, {x[2, 1], x[2, 2]}, Max[a, b]},
{{x[1, 1], x[1, 2]}, {x[2, 1], x[2, 2]}, Max[c, d]},
{{x[1, 1], x[1, 2]}, {x[2, 1], x[2, 2]}, Max[e, f]}} *)
Or maybe you wanted the append-ing to happen at the lower level:
Apply[Map[Append[#2], #1] &] /@ Comap[{fn, Max}] /@ testlist
(* {{{x[1, 1], x[1, 2], Max[a, b]}, {x[2, 1], x[2, 2], Max[a, b]}},
{{x[1, 1], x[1, 2], Max[c, d]}, {x[2, 1], x[2, 2], Max[c, d]}},
{{x[1, 1], x[1, 2], Max[e, f]}, {x[2, 1], x[2, 2], Max[e, f]}}} *)
Per the comment, if the desire is to simply avoid computing max twice, then just wrap the expression that already works with With:
With[
{max = Max[#]},
Append[{max}, f[max]]] & /@ testlist
To address the update to the question, here is a function that does the work (assuming yourFunction behaves like FactorInteger)
MapApply[Append]@*Thread@*Comap[{yourFunction, Identity}]@*Max
Demonstration:
testlist = {{100, 200}, {300, 400}, {500, 600}};
expected = {{{2, 3, 200}, {5, 2, 200}},
{{2, 4, 400}, {5, 2, 400}},
{{2, 3, 600}, {3, 1, 600}, {5, 2, 600}}};
oldFn = FactorInteger;
newFn = MapApply[Append]@*Thread@*Comap[{oldFn, Identity}]@*Max;
actual = newFn /@ testlist;
actual == expected
(* True *)
You could bundle this up into your own function generator:
fancy[fn_] := MapApply[Append]@*Thread@*Comap[{fn, Identity}]@*Max;
actual = fancy[FactorInteger] /@ testlist;
actual == expected
(* True *)