8

I am trying to get unique items from an object so I am starting with a set however I need the values to be returned as a list for the visualforce <apex:selectOptions> component. I have tried the code below, and variations, but I keep getting errors related to the type not being set correctly. Can anyone help me out? Is there a better way of populating a list with unique values from a SOQL query?

    public List<SelectOption> getItems() {

        Set<License__c> license = new Set<License__c>( [SELECT Name FROM License__c] );
        List<SelectOption> options = new List<SelectOption>();
            options.addAll(license);
        return options;
}

5 Answers 5

8

No need to work with lists and sets if you group-by in the query:

    public List<SelectOption> getItems() {
        List<SelectOption> options = new List<SelectOption>();
        for(AggregateResult l : [SELECT Name FROM License__c GROUP BY Name]){ 
            options.add(new SelectOption(String.valueOf(l.get('Name')),String.valueOf(l.get('Name'))));
        }
        return options;
    }
3
  • I like you method the best so far but it is generating an error.
    – Matt M
    Commented Jun 9, 2016 at 19:02
  • Loop variable must be an SObject or list of AggregateResult
    – Matt M
    Commented Jun 9, 2016 at 19:02
  • 1
    Ah you're right it has to loop through aggregateresult because of the grouping. I corrected that now. Slightly less clean because we then have to fetch the values and convert to string, although still the most efficient way of doing it I believe Commented Jun 9, 2016 at 19:10
12

Simplest way:

new List<String>( new Set<String> {'a', 'b', 'c'} );

3
  • 2
    Perfect. Also Set<String> foo = new Set<String>(); new List<String>(foo); Commented Apr 7, 2022 at 17:48
  • 1
    @ShaneK that's exactly same
    – dzh
    Commented Apr 16, 2022 at 9:46
  • 1
    It is essentially the same. But the point is you can initialize a Set and alter it as much as you like, and then cast it to a List later. Its just for clarity because at first glance your example might suggest you have to use a static initializer. Commented Apr 17, 2022 at 20:47
2

You need to create a list of SelectOptions. The set you have is not the same type, so you have to iterate over them, and create SelectOption objects, then add them to the list.

for (License__c l: license) {
    options.add(new SelectOption(l.Name, l.Id));
}
1

If someone like me enjoys using the array notation for the lists like:

Id[] ids = new Id[]{};

instead of,

List<Id> ids = new List<Id>();

to create a list from a set would be as the following,

Set<Id> idSet = new Set<Id>();
Id[] idList = new List<Id>(idSet);

So Set and Map don't have any other notations as far as I know. So assuming we have a Set of IDs called idSet. If you want to use the array notation to create a list and populate it with all the IDs from idSet, you would still need to use the List notation on the right-hand side of the expression. So you CAN NOT do,

Id[] idList = new Id[](idSet);

I hope this helps you sugar-coat your code the way you like it. Cheers!

0

If you want unique elements, you could tweak your SOQL to get distinct names. Since the DISTINCT keyword is not supported by SOQL, one workaround is to use GROUP

SELECT Name, COUNT(Name) FROM License__c GROUP BY Name

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .