Hi, I'm making a mobile app. I would like to compare two lists with identical structure, with one particular list having all of the records and more than the other one, and somehow obtain a new list with the additional records that the smaller list does not have. How might I go about doing that, without using any forge component?

Hi Li Han,

Assuming that the lists are in the same order, I think the most straightforward thing is to iterate over the large list (with a For Each), and checking whether the Current element is equal to the pertaining element in the shorter list (keeping an index for the shorter list, and indexing it instead of using the Current). If not, it's an element only in the large list, so you can add that element to another List that keeps track of the additional records.

If the lists are not in the same order, use ListSort to sort them, or use the SortRecordList Forge component for more complex sorts. If sorting is not an option for whatever reason, comparison will be a lot slower. In that case you can iterate over the large lists and use a ListAny to check whether the element is present in the shorter list.

Hi Li Han,

In addition to the solution that Kilian provided, I want to suggest another.

If your "large" list is a lot more larger than the "shorter" list, you could, for sake of performance, choose to:

- iterate over the short list, and check if the element of the "short" list exists in the "large" list using ListIndexOf.

- save each returned index number in an long integer list

- duplicate the "large" list

- iterate the long integer list and do a delete ListRemove on the duplicated "large" list

- Now you have all the elements you are looking for

Regards,

Daniel




Hi Daniël,

I'm not sure whether that's more performant. Also, there's a flaw: since you are ListRemoving elements, the indexes saved in the Integer List should be corrected for that, or you'll end up removing the wrong elements (and possibly getting an Exception for removing an element that's not present).

Kilian Hekhuis wrote:

Hi Daniël,

I'm not sure whether that's more performant. Also, there's a flaw: since you are ListRemoving elements, the indexes saved in the Integer List should be corrected for that, or you'll end up removing the wrong elements (and possibly getting an Exception for removing an element that's not present).

Hi Kilian,

Regarding the performance, I was thinking in a use case where the large list has hundreds or thousands of records the the short list only a handful. Thinking that with the solution I propose prefer less iterations over a small list rather than many iterations over a large list. Anyhow I agree that one should only seek for a more optimized solution if there is really need too, and compare both solutions could give an answer to that.

You  are totally right regarding the flaw in my solution, should have thought a little bit more about it. It will work I if you would do the for each over the long integer list from back to front.

Regards,

Daniel


Hi, thank you Killian and Daniel for your ideas. Unfortunately, I can only mark one as an answer, but both methods are actually rather ingenious!

Kilian Hekhuis wrote:

Hi Li Han,

Assuming that the lists are in the same order, I think the most straightforward thing is to iterate over the large list (with a For Each), and checking whether the Current element is equal to the pertaining element in the shorter list (keeping an index for the shorter list, and indexing it instead of using the Current). If not, it's an element only in the large list, so you can add that element to another List that keeps track of the additional records.

If the lists are not in the same order, use ListSort to sort them, or use the SortRecordList Forge component for more complex sorts. If sorting is not an option for whatever reason, comparison will be a lot slower. In that case you can iterate over the large lists and use a ListAny to check whether the element is present in the shorter list.

Hello, I am trying to find records in one aggregate that are not in another aggregate. For the records not in the other aggregate, I want to add them to a list. I am confused about this part of your instructions:  (keeping an index for the shorter list, and indexing it instead of using the Current). Could you explain in more detail please?


Hi Andi,

Assuming you know for sure that all elements of Aggregate2 are also in Aggregate1, and Aggregate1 may contain additional records, you For Each over Aggregate1. For Aggregate2, you create a Local Variable, lets call it "Index", which an initial value of 0. Each iteration of the For Each, you compare the Current of Aggregate1 with the item at position Index of Aggregate2. So say both Aggregates have a single Entity called "MyEntity", you compare the content of Aggregate1.List.Current.MyEntity with Aggregate2.List[Index].MyEntity.

If they are equal, you advance to the next item; for Aggregate1 this will be done automatically because of the For Each, for Aggregate2 you increase Index by one (so use an Assign to assign Index + 1 to Index).

If the are not equal, you have an element in Aggregate1 that is not in Aggregate2, so you add the Current of Aggregate1 to your List using a ListAppend. In this case, you do not increase Index, as you want to compare the next record of Aggregate1 with the current record of Aggregate2.

Hi Kilian,


I have the same use case as Andi. Thanks for the clear explanation.

When you mean use an assign Index + 1 to Index,

Do you mean assigning Aggregate2.List[Index].MyEntity + 1 ?


Best Regards,

Wen Kai





Hi Wen Kai,

I mean what I wrote: "use an Assign to assign Index + 1 to Index". You are looping over a list, so the index needs to be increased. Please try to understand what you are doing, and why.

Hey Li Han Ong

I did a similar logic maybe this can help in someway



Regards,

Flávio

Hi Flávio,


I have a similiar situation same as Li Han.

Do you mind sharing a sample oml ? 

Thank you.


Best Regards,

Wen Kai

Hi Wen Kai,

I assume you are a software developer. We have explained what algorithm to use, and given assumption 1, you should be able to figure this out on your own.

I'll close the topic, since it has a solution, and multiple explanations.