dummzeuch 1505 Posted November 28, 2022 If I want to get the topmost element of a stack (System.Generics.Collections.TStack<T>), without removing it, I use TStack<T>.Peek. Is there any way to get the second to topmost element? I looked at the sources and found none, so the only way I could come up with is: TopElement := MyStack.Pop; SecondElement := MyStack.Peek; // <== I want this one MyStack.Push(TopElement); if SecondElement = SearchedForElement then begin // ... end; Alternatively I would settle for a way to check whether the stack contains a given element: if MyStack.Contains(SearchedForElement) then begin // ... end; But there doesn't seem to be such a method either. Is there maybe a different container for that? Share this post Link to post
David Heffernan 2345 Posted November 28, 2022 15 minutes ago, dummzeuch said: Is there maybe a different container for that? Seems like you want TList<T> Share this post Link to post
Dmitry Arefiev 101 Posted November 28, 2022 MyStack.List[MyStack.Count - 2] Share this post Link to post
dummzeuch 1505 Posted November 28, 2022 3 minutes ago, Dmitry Arefiev said: MyStack.List[MyStack.Count - 2] TStack<T> does not have a List property (at least in Delphi 10.2) Share this post Link to post
dummzeuch 1505 Posted November 28, 2022 20 minutes ago, David Heffernan said: Seems like you want TList<T> That's one option, yes, but then I would have to implement the stack functionality myself. Share this post Link to post
Dmitry Arefiev 101 Posted November 28, 2022 MyStack.ToArray[MyStack.Count - 2] Share this post Link to post
David Heffernan 2345 Posted November 28, 2022 3 hours ago, Dmitry Arefiev said: MyStack.ToArray[MyStack.Count - 2] Make me yak Share this post Link to post
David Heffernan 2345 Posted November 28, 2022 3 hours ago, dummzeuch said: That's one option, yes, but then I would have to implement the stack functionality myself. Well, what's stopping you doing that? It's not a challenge. If you want random access to the entire collection, a stack isn't for you. Share this post Link to post
dummzeuch 1505 Posted November 28, 2022 7 minutes ago, David Heffernan said: Well, what's stopping you doing that? It's not a challenge. If you want random access to the entire collection, a stack isn't for you. I don't want random access to the complete stack, just to the second to topmost entry. And for that I have got a solution that works but is clunky. Since I have only recently begun to use the generics that come with the RTL (Yes, I'm late to the party), I was hoping I might have overlooked something like TStack<T>.Peek(_IndexFromTop: integer): T. Apparently there isn't. Share this post Link to post
David Heffernan 2345 Posted November 28, 2022 Adding push pop and peek to TList is incredibly simple. I thought you wanted access to them all because you talked about searching the collection for a specific item. Do you not need to do that? Share this post Link to post
dummzeuch 1505 Posted November 28, 2022 (edited) 23 minutes ago, David Heffernan said: Adding push pop and peek to TList is incredibly simple. Yeah. I've been there: "It's simple, I'll write my own". [writes his own, overlooks a corner case and then takes 5 hours to find that bloody bug] 23 minutes ago, David Heffernan said: I thought you wanted access to them all because you talked about searching the collection for a specific item. Do you not need to do that? No. As I wrote: 5 hours ago, dummzeuch said: Alternatively I would settle for a way to check whether the stack contains a given element: if MyStack.Contains(SearchedForElement) then begin // ... end; But there doesn't seem to be such a method either. (emphasis mine) Edited November 28, 2022 by dummzeuch Share this post Link to post
programmerdelphi2k 237 Posted November 28, 2022 (edited) using "System.Generics.Collections" or "System.Contnrs"? uses // System.Contnrs; System.Generics.Collections; var MyStackList: TStack<TButton>; // MyStackList: TStack; procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin // System.Generics.Collections.pas MyStackList := TStack<TButton>.Create; try // MyStackList.TEnumerator ... // i := MyStackList.Count - 2; // before last if (i >= 0) then MyStackList.List[ ...i...] .Caption := 'hello world'; // // MyStackList.Push( buttonX ) // MyStackList.Pop; // MyStackList.Peek; // MyStackList.Count; // *************************// // System.Contnrs.pas; // MyStackList.AtLeast( n ) // MyStackList.Push() // add // MyStackList.Pop; //remove e return // MyStackList.Peek; // next on list, no remove // MyStackList.Count // how many finally MyStackList.Free; end; end; Edited November 28, 2022 by programmerdelphi2k Share this post Link to post
Fr0sT.Brutal 900 Posted November 28, 2022 @programmerdelphi2k I wonder how much time it will take for you to discover that the code snippets should be posted inside CODE tags Share this post Link to post
programmerdelphi2k 237 Posted November 28, 2022 sorry, but really I dont see it... fixing now! Share this post Link to post
David Heffernan 2345 Posted November 28, 2022 39 minutes ago, dummzeuch said: Yeah. I've been there: "It's simple, I'll write my own" Push is Add. Pop is Extract(Count-1) and Peek is Items[Count-1] Contains won't help you because it checks the entire collection, not just the top two. Share this post Link to post
Stefan Glienke 2002 Posted November 28, 2022 (edited) type TMyStack<T> = class(TStack<T>) function Peek(indexFromTop: Integer): T; overload; inline; end; {$IF RTLVersion < 33} type TStackAccess<T> = class(TEnumerable<T>) FItems: TArray<T>; property List: TArray<T> read FItems; end; {$IFEND} function TMyStack<T>.Peek(indexFromTop: Integer): T; begin Result := {$IF RTLVersion < 33}TStackAccess<T>(Self).{$IFEND}List[Count - indexFromTop - 1]; end; Edited November 28, 2022 by Stefan Glienke 1 Share this post Link to post
dummzeuch 1505 Posted November 28, 2022 So basically, the answer is "No". Share this post Link to post
David Heffernan 2345 Posted November 28, 2022 1 hour ago, dummzeuch said: So basically, the answer is "No". You can look at the list of public methods and properties. Why do you need us to tell you that what you want isn't there? Didn't all the responses suggesting alternatives indicate that? Share this post Link to post
Stefan Glienke 2002 Posted November 29, 2022 (edited) 21 hours ago, dummzeuch said: Is there any way to get the second to topmost element? Yes. If you wanted to know if there is any method that does that then you should have expressed your question more precisely. But hey let's ask a vague question and then offend anyone providing help by ignoring them. Edited November 29, 2022 by Stefan Glienke Share this post Link to post
dummzeuch 1505 Posted November 29, 2022 (edited) Yeah, that's me. Ok, the problem seems to be that I'm unable to ask the question so people understand it. Sorry for that, maybe I should stick with the German forum. What I wanted to know is if there is an easier way to get to the second topmost item than the one I described in my original post. The answer to that seems to be "No", as far as I understand it. So I've put those 3 lines of code into a function and live with it. Edited November 29, 2022 by dummzeuch Share this post Link to post
Stefan Glienke 2002 Posted November 29, 2022 (edited) 2 hours ago, dummzeuch said: What I wanted to know is if there is an easier way to get to the second topmost item than the one I described in my original post. The answer still is yes - your code actually mutated the stack - all proposed answers avoided that - some even avoided any allocation and mine even gave you a drop-in solution. The only question that could be answered with "No" would have been: Is there any solution to this problem where I don't have to write any code for? Edited November 29, 2022 by Stefan Glienke Share this post Link to post
David Heffernan 2345 Posted November 29, 2022 2 hours ago, dummzeuch said: So I've put those 3 lines of code into a function and live with it. You better hope you have two or more items in the collection when you execute that code. And as Stefan says, your code is nearly as bad a way to do this as possible. I think the only worse way is to call ToArray. There are plenty of ways to do this well, and it baffles me that you choose the poor solution when good solutions exist. Does quality not matter? Share this post Link to post
dummzeuch 1505 Posted November 29, 2022 Please let's agree to disagree. My solution works for my specific problem and is easy to understand. It's also fast enough for me and since there is no multithreading involved temporarily changing the stack doesn't matter. Quality does indeed matter, but only as far as it makes any difference to the problem at hand. This is basically a throw away program which I hope I will never have to use again (yeah, right, dream on). Share this post Link to post
programmerdelphi2k 237 Posted November 29, 2022 On 11/28/2022 at 11:22 AM, programmerdelphi2k said: i := MyStackList.Count - 2; // before last if (i >= 0) then getting obj = MyStackList.List[ ...i...] @dummzeuch this dont help you? see above Share this post Link to post
David Heffernan 2345 Posted November 29, 2022 On 11/28/2022 at 2:03 PM, dummzeuch said: Yeah. I've been there: "It's simple, I'll write my own". [writes his own, overlooks a corner case and then takes 5 hours to find that bloody bug] 35 minutes ago, dummzeuch said: This is basically a throw away program which I hope I will never have to use again (yeah, right, dream on). It's almost as if posts from two completely different threads have somehow been interspersed with each other Share this post Link to post