dummzeuch 1505 Posted May 19, 2023 (edited) I would like to have a set of some objects of the same class e.g. TEdit. Of course TEdit is not an ordinal type, so set of TEdit won't work. Is there some (generics?) container type that lets me Add Object instances to it, ignoring duplicates Check if an object instance is in the list Or even better lets me enumerate over all the object instances in the list So I can do something link this: var EditSet = TSet<TEdit>; ed: TEdit; begin EditSet.Add(Edit1); EditSet.Add(Edit1) EditSet.Add(Edit2); EditSet.Add(Edit4); if EditSet.Contains(Edit1) then Edit1.Text := 'Was in set'); if EditSet.Contains(Edit3) then Edit3.Text := 'Was in set'); // or even better: for ed in EditSet do ed.Text := 'Was in set'; end; I'd prefer using something ready made from the RTL, if it exists. Edited May 19, 2023 by dummzeuch Add Edit1 twice Share this post Link to post
David Heffernan 2345 Posted May 19, 2023 (edited) Spring has a collection that meets your needs. With pure rtl you can fake it with a geneic dictionary. Edited May 19, 2023 by David Heffernan Share this post Link to post
Brandon Staggs 278 Posted May 19, 2023 (edited) TDictionary<TObject, Boolean> Your objects are the keys, and the value can essentially be ignored. Use AddOrSetValue, and KeyExists. Might go the next step and just create some kind of hash table if I were doing this a lot. I doubt the overhead of having an un-needed value is worth it though. Edited May 19, 2023 by Brandon Staggs 2 Share this post Link to post
Lajos Juhász 293 Posted May 19, 2023 You could also use a generic list? That also has everything you wrote above. Share this post Link to post
dummzeuch 1505 Posted May 19, 2023 (edited) 11 minutes ago, Lajos Juhász said: You could also use a generic list? That also has everything you wrote above. What happens, when I add the same object twice? In a set, the duplicate will be discarded, but in a list? Edited May 19, 2023 by dummzeuch Share this post Link to post
Attila Kovacs 629 Posted May 19, 2023 1 hour ago, dummzeuch said: Is there some (generics?) container type that lets me https://stackoverflow.com/questions/19466038/finding-common-elements-in-two-arrays/19524788#19524788 1 1 Share this post Link to post
Lajos Juhász 293 Posted May 19, 2023 22 minutes ago, dummzeuch said: What happens, when I add the same object twice? In a set, the duplicate will be discarded, but in a list? The list would contain the control twice (like a multiset). If you don't want an object twice you can before add check indexof. Share this post Link to post
programmerdelphi2k 237 Posted May 19, 2023 (edited) a little test using TList + TEdits LMyEdits.LEAddEdit(LEdit); VCL_TList_TEdit_class.7z Edited May 19, 2023 by programmerdelphi2k Share this post Link to post
David Heffernan 2345 Posted May 19, 2023 2 hours ago, Lajos Juhász said: You could also use a generic list? That also has everything you wrote above. Doesn't handle duplicates Share this post Link to post
Lajos Juhász 293 Posted May 19, 2023 4 minutes ago, David Heffernan said: Doesn't handle duplicates the original post doesn't said if it's a multiset or not. Share this post Link to post
David Heffernan 2345 Posted May 19, 2023 1 minute ago, Lajos Juhász said: the original post doesn't said if it's a multiset or not. Yes they did 3 hours ago, dummzeuch said: Add Object instances to it, ignoring duplicates Share this post Link to post
Fr0sT.Brutal 900 Posted May 23, 2023 TList descendant with overridden .Add that would run Find before actual adding? Share this post Link to post
David Heffernan 2345 Posted May 23, 2023 All these people suggesting TList (i.e. an array) are just asking for performance problems if ever the collection has a significant size. 1 Share this post Link to post
Anders Melander 1782 Posted May 23, 2023 24 minutes ago, David Heffernan said: if ever the collection has a significant size With a list of TEdits? Not likely. I would go for an encapsulated TList<T>: type TSetOfStuff<T> = class private FList: TList<T>; public function Contains(const Value: T): boolean; function Add(const Value: T): integer; procedure Remove(const Value: T); function GetEnumarator: TEnumerator<T>; end; function TSetOfStuff<T>.Contains(const Value: T): boolean; begin var Index: integer; Result := FList.BinarySearch(Value, Index); end; function TSetOfStuff<T>.Add(const Value: T): integer; begin if (not FList.BinarySearch(Value, Result)) then FList.Insert(Result, Value); end; procedure TSetOfStuff<T>.Remove(const Value: T); begin var Index: integer; if (FList.BinarySearch(Value, Index)) then FList.Delete(Index); end; function TSetOfStuff<T>.GetEnumarator: TEnumerator<T>; begin Result := FList.GetEnumerator; end; etc... 1 Share this post Link to post
dummzeuch 1505 Posted May 23, 2023 This was about a set with at most 20 different entries, so performance would most likely not have been an issue (when I asked the question, it was only 5). I have solved the actual problem differently by now. A set is still involved, but not a set of object instances but simply a classical set of an enum. Share this post Link to post
David Schwartz 426 Posted May 23, 2023 I'm unclear why you keep thinking of it like a Set. In my mind, it's just a collection (bag) of objects and you want to know if a given object is in it or not. If so, you get back True. If not, you get back False. If the semantics are that you don't want dups, then you only add to the bag after you get back False from a test for inclusion. In the DB world, I've seen lots of times when someone creates a method like, "AddOrUpdateWidget( aWidget : TWidget )" that subsumes the test to see if the widget is already there or not. Share this post Link to post
David Heffernan 2345 Posted May 24, 2023 9 hours ago, David Schwartz said: I'm unclear why you keep thinking of it like a Set. In my mind, it's just a collection (bag) of objects and you want to know if a given object is in it or not. If so, you get back True. If not, you get back False. If the semantics are that you don't want dups, then you only add to the bag after you get back False from a test for inclusion. What you've described is a set. So that's why he keeps thinking of it as a set. 1 Share this post Link to post
David Schwartz 426 Posted May 24, 2023 14 hours ago, David Heffernan said: What you've described is a set. So that's why he keeps thinking of it as a set. A "set" in Pascal is a collection of the same types of things where their value reflects a position in the set, meaning they can be expressed as ordinal values between 0 and the upper limit of members the compiler allows. If you want to use objects then their ordinal values can easily correspond to their memory location cast as an integer, which would be a 32- or 64-bit value, and the set itself would take up far more than available memory. Alternatively, the values could be hashed to result in a smaller container. But there's also this data structure called a "bag" which is an unordered collection of related things where you're only interested in whether something is "in the bag" or not. That's how databases tend to be organized, and indices are used to make tests for inclusion go much faster. In Pascal, a "set" is tightly correlated with its implementation, where members have ordinal values corresponding to unique bits in the allocated space. The compiler manages those values, in contrast to the values of object locations in memory, which are highly random. Look, I didn't invent any of this. I rarely use "sets" in Pascal because of this inherent limitation. I work mostly with objects, and you cannot put an object into a Pascal "set" nor test for its presence. But from a theoretical viewpoint, EVERYTHING is a "set" in my mind, which really doesn't resolve anything from a programming standpoint. Share this post Link to post
David Heffernan 2345 Posted May 24, 2023 7 minutes ago, David Schwartz said: A "set" in Pascal I'm not talking about a Pascal or Delphi set. I'm talking about a set in general, non language or implementation terms. And that's that the question was about. Also there are a number of libraries that define set collections that aren't native Delphi set types. I'm thinking spring4d for example. Share this post Link to post
Fr0sT.Brutal 900 Posted May 25, 2023 Quote In computer science, a set is an abstract data type that can store unique values, without any particular order. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set. https://en.wikipedia.org/wiki/Set_(abstract_data_type) 2 Share this post Link to post