0

I'm trying to fetch the randomly specific number of items from one list and add them to the other list but without duplication.

For example: pick three random items from the list randomly and put them into another list. This is what I have achieved so far but this could pick the duplicate item again.

List itemList = ['NAME1', 'NAME2', 'NAME3', 'NAME4', 'NAME3', 'NAME5', 'NAME2'];

List randomItems = [];


for(var i=0; i<=2; i++){ // run the loop for three times
  int randomNumber = Random().nextInt(itemList.length); //generate random number within itemList range
  randomItems.add(itemList[randomNumber]); // duplication occur, for example: NAME2 could be added two times
}
1
  • List randomItems = [...([...{...itemList}]..shuffle()).take(3)]; would be a one-liner. Possibly not optimal performance-wise, because of allocating a set, but probably also not far off since you need to do de-duplication somehow. Commented May 30, 2022 at 11:03

1 Answer 1

4

There are several steps we can do to solve this problem. First, we want to get rid of the duplicate elements in the list. We can here do that by converting the list to a Set:

  List<String> itemList = [
    'NAME1',
    'NAME2',
    'NAME3',
    'NAME4',
    'NAME3',
    'NAME5',
    'NAME2'
  ];
  Set<String> itemSet = itemList.toSet();
  print(itemSet); // {NAME1, NAME2, NAME3, NAME4, NAME5}

Then, we want to extract 3 random elements from this new Set in such a way that we can't select the same element twice. The easiest way to solve this is by shuffle the elements randomly and then take elements from our collection. But Set does not have the concept of any specific "order" and we can't therefore shuffle our Set.

So let's convert our Set back to a List:

  Set<String> itemSet = itemList.toSet();
  List<String> itemListFromSet = itemSet.toList();
  print(itemListFromSet); // [NAME1, NAME2, NAME3, NAME4, NAME5]

We can then shuffle this new list:

  itemListFromSet.shuffle();
  print(itemListFromSet); // [NAME3, NAME2, NAME4, NAME5, NAME1]

If we then want 3 random selected elements, we can just take 3 elements from this randomly ordered list. So e.g. (take returns an iterable which we then makes a new list of):

List<String> randomItems = itemListFromSet.take(3).toList();

A complete solution would look like:

void main() {
  List<String> itemList = [
    'NAME1',
    'NAME2',
    'NAME3',
    'NAME4',
    'NAME3',
    'NAME5',
    'NAME2'
  ];
  Set<String> itemSet = itemList.toSet();
  List<String> itemListFromSet = itemSet.toList();

  itemListFromSet.shuffle();

  List<String> randomItems = itemListFromSet.take(3).toList();

  print(randomItems); // [NAME5, NAME2, NAME4]
}

Which can be reduced down to:

void main() {
  List<String> itemList = [
    'NAME1',
    'NAME2',
    'NAME3',
    'NAME4',
    'NAME3',
    'NAME5',
    'NAME2'
  ];
  List<String> randomItems =
      (itemList.toSet().toList()..shuffle()).take(3).toList();

  print(randomItems); // [NAME3, NAME4, NAME2]
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, mate! Appreciate that! By the way, could you tell me that how to use toSet method on list of map
Check the following question stackoverflow.com/questions/72418071/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.