ID:1811414
 
(See the best response by Lummox JR.)
Code:
mob/proc/Pendulum()

if(isfrozen()) return
if(!PZ1 || !PZ2) return

var/PL_1 = PZ1.scale_b
var/PL_2 = PZ2.scale_r

var/list/monsters = list()
var/list/summons = list()
var/z = 5

for(var/obj/cards/monster/C in usr.Hand)
if((C.level < PL_2 && C.level > PL_1)||(C.level > PL_2 && C.level < PL_1))
monsters += C
for(var/obj/cards/monster/C in usr.PPile) if(!isnull(C.pendulum))
if((C.level < PL_2 && C.level > PL_1)||(C.level > PL_2 && C.level < PL_1)||(C.rank < PL_2 && C.rank > PL_1)||(C.rank > PL_2 && C.rank < PL_1))
monsters += C

if(!monsters) return

if(Monster1) z--
if(Monster2) z--
if(Monster3) z--
if(Monster4) z--
if(Monster5) z--

if(!z) return

isbusy = 1

SortByName(monsters)

var/obj/portal/P = new(src)
ObjGrid += P

while(monsters.len)

var/T = input("Choose monsters to Pendulum Summon.\n(hit cancel when done)","[summons.len] so far ([z-summons.len] empty Zones)") as null|obj in monsters
if(!T) break

summons += T
monsters -= T

if(summons.len >= z) break


Problem description:

So this code here is pulling a list of all possible objects from 2 different inventories. Storing them in list "monsters" then asking the player for a selection of up to 5 of them depending on how many slots they have available. Adds all those selections to list "summons" so they can be summoned into those slots.

Here's the issue I'm facing...
There are 2 different inventories. Players need to know which of the 2 inventories they're pulling each object from in the input list. The input list combines like entries though.

So instead of them coming out like....

AAA
AAA
BBB
CCC
DDD
DDD

it just comes out as...

AAA
BBB
CCC

I really would like them to be listed like...

AAA (Hand)
AAA (Deck)
BBB (Hand)
CCC (Deck)
DDD (Hand)
DDD (Deck)

I've got lists which do this similarly in other aspects of the game but those are for a fixed number of objects.

I need all of these objects...
var/obj/cards/monster/C in usr.Hand
var/obj/cards/monster/C in usr.PPile

To be listed in the input by...
C.name (C.CrdLoc)
Let the player pick from that list. Then add the associated object to the second list to be summoned.

I just cannot seem to win with lists lately. New problems keep popping up for me one after the other.
Best response
I can help with part of your problem at least. If you want cards sorted by name, then location, you need a sort routine. Since the list sizes are likely to be small, I recommend insertion sort.

proc/CardSort(list/cards)
var/cmp, unsorted, i, first, last
var/obj/cards/monster/C1
var/obj/cards/monster/C2
var/name, loc
// unsorted: start of unsorted cards
for(unsorted=2, unsorted<=cards.len, ++unsorted)
C1 = cards[unsorted]
name = lowertext(C1.name)
loc = C1.CrdLoc
// this is a binary insertion sort:
// find the insertion point with binary search
first = 1
last = unsorted - 1
while(first <= last)
i = (first+last) >> 1
C2 = cards[i]
cmp = cmptext(name, lowertext(C2.name)) || cmptext(C2.CrdLoc, loc)
if(cmp < 0) last = i-1
else first = i+1
if(first < unsorted)
cards.Cut(unsorted, unsorted+1)
cards.Insert(first, C1)
The cards themselves don't need to be sorted in any particular order for the purposes of this. What's important is that the input selection show the card's location and doesn't combine the cards from 2 different locations.

If I had say...
2 AAA in my hand. 2 BBB in my hand. 2 AAA in my deck. and 2 BBB in my Deck.

Right now it would show as
AAA
BBB

The input selection needs to show.
AAA (Hand)
AAA (Deck)
BBB (Hand)
BBB (Deck)

I dont need all 8 individual cards being shown. Those 4 entries are all that are needed. It can combine the copies in the hand together since that doesn't matter. The order those 4 entries are displayed doesn't matter either.
What you need then is an associative list.

var/list/choices = new
var/obj/cards/monster/C
for(C in usr.Hand) choices["[C.name] (Hand)"] = C
for(C in usr.PPile) choices["[C.name] (Deck)"] = C
C = input(...) as null|anything in choices
C = choices[C]