Check duplicated values in ds_list

waliente

Member
Hi everyone, i have an issue about find duplicated values in a ds_list.

This is the example:

Code:
var list = [1,2,3,3,4,5,6,6,7,8,8,9,10] // this is only for example, in the real code this is a ds_list
var tempList = ds_list_create();

for(var i = 0; i < ds_list_size(list); i++) {

    var _value = ds_list_find_value(list, i);

    ...

}

ds_list_destroy(tempList);

I need to find the duplicates values and store its in a new temporary list. How can i do that?
 

Yal

🐧 *penguin noises*
GMC Elder
If the list is sorted like in your example, you could do something like this:
  • for every value c in the list,
    • store the value in florp
    • for every value d in the list, starting at c + 1,
      • if the value is equal to florp,
        • move it over to the list of duplicates
        • since we just shortened the list by 1, reduce d by 1 so we don't skip any values
      • if the value is not equal, abort the loop (over d)
 

waliente

Member
After your advices i've done this:


GML:
// i've creted two temporary ds_list
var _valueList            = ds_list_create(); // this is created to conver elements string value in a number value
var _playableCardList    = ds_list_create(); // this will be the finally list to use

// i've converted the incoming list with string values with a custom function that returns a number
for(var i = 0; i < ds_list_size(hand); i++) {
    ds_list_add(_valueList, cardValueToNumber(ds_list_find_value(hand, i).Value));
}

// then i sorted it
ds_list_sort(_valueList, true);

// theni've followed you advices doing this code
for(var i = 0; i < ds_list_size(_valueList); i++) {
    var c = ds_list_find_value(_valueList, i);
    var d = c + 1;

    if (ds_list_find_value(_valueList, i) == c) {
        ds_list_add(_playableCardList, c);
        d -= 1;
    } else {
        break;
    }
}

// then i log the last list
for (var i = 0; i < ds_list_size(_playableCardList); i++) {
    show_debug_message(ds_list_find_value(_playableCardList, i))
}
The results that this code is given to me seems to be all the incoming list values and not only the duplicated values... I'm sure i'm missing something but maybe i'm near to the expected result. :D

What i have missed to return duplicated results in the final list?
 

Nidoking

Member
var c = ds_list_find_value(_valueList, i);
var d = c + 1;
if (ds_list_find_value(_valueList, i) == c) {
You've stored the value of the list element at i in c, then done nothing to either of them, then checked to see whether the element at i is still c. This will always be true. If you're sorting the list, you only need to check the next value after each unique one, until you find something new.
 

waliente

Member
You've stored the value of the list element at i in c, then done nothing to either of them, then checked to see whether the element at i is still c. This will always be true. If you're sorting the list, you only need to check the next value after each unique one, until you find something new.
Sincerely.... i don't think i understand what you mean...
 

Yal

🐧 *penguin noises*
GMC Elder
GML:
   var d = c + 1;

    if (ds_list_find_value(_valueList, i) == c) {
        ds_list_add(_playableCardList, c);
        d -= 1;
    } else {
        break;
    }

Nonono, that's all messed up... you should use a second loop like this:
GML:
   for(var d = i + 1; d < ds_list_size(_valueList); d++) {

    if (ds_list_find_value(_valueList, d) == c) {
        ds_list_add(_playableCardList, c);
        d -= 1;
    } else {
        break;
    }
 

Nidoking

Member
Nonono, that's all messed up... you should use a second loop like this:
GML:
   for(var d = i + 1; d < ds_list_size(_valueList); d++) {

    if (ds_list_find_value(_valueList, d) == c) {
        ds_list_add(_playableCardList, c);
        d -= 1;
    } else {
        break;
    }
I don't think this infinite loop is a good idea. You need to actually remove the element from the list if you're going to decrement the loop counter inside the loop.
 

Nidoking

Member
Sincerely.... i don't think i understand what you mean...
x = 5;

if (x == 5)
{}

Tell me, when will this ever not be true? When will x be a value other than 5 when it does the check? Can you think of a situation where that will happen? The code you wrote is exactly the same.
 

Tornado

Member
Just use temporary map for checking the duplicates:
Code:
...
...
...
var _tempMap = ds_map_create();
for (i=0; i < ds_list_size(_valueList); i++) {
    var item = ds_list_find_value(_valueList, i);
    if (_tempMap[?item] == undefined) {
        ds_list_add(_playableCardList, item);
        ds_map_add(_tempMap, item, "dummy");
    }
}
ds_map_delete(_tempMap);

for (var i = 0; i < ds_list_size(_playableCardList); i++) {
    show_debug_message(ds_list_find_value(_playableCardList, i))
}
 
Last edited:

waliente

Member
Hi everyone and thanks for all your replies.

Actually i've solved in this way:


GML:
for(var i = 0; i < ds_list_size(_valueList); i++) {
    var card = ds_list_find_value(_valueList, i);
   
    for(var a = i + 1; a < ds_list_size(_valueList); a++) {
        var cardA = ds_list_find_value(_valueList, a);
       
        if (cardA == card) {
            show_debug_message(string(card) + " " + string(cardA));
        }

        // ...
    }
}
 
Top