How can I remove any item (first one is easy) from a list

Is has to be easier than this:


set lista_orig to {"1 ", "2 ", "3 ", "4 ", "5 ", "6 ", "7 ", "8 ", "9 ", "10"}

set i to 2 -- the item to extract

try
	set lista_truncada to sacar_item(lista_orig, i)
on error
	display dialog "Not posible!" buttons {"OK"} default button 1
	set lista_truncada to la_lista
end try
return (lista_orig) & return & return & (lista_truncada)

on sacar_item(lista, i)
	if i = 1 then
		set lista to (rest of lista)
		return lista
	else if i > 1 then
		set el_primero to (item 1 of lista)
		set (item 1 of lista) to (item i of lista)
		repeat until i = 2
			set (item i of lista) to (item (i - 1) of lista)
			set i to (i - 1)
		end repeat
		set lista to (rest of lista)
		set (item 1 of lista) to el_primero
		return lista
	else if i < 1 then
		set lista to (lista div 0) -- crashes try
	end if
end sacar_item

rest of “list” is just for the first one, and all the others?

A faster way would be:

set mylist to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

removeItem(mylist, 9)
--> {1, 2, 3, 4, 5, 6, 7, 8, 10}

on removeItem(theList, theItem)
	--basic error checking
	if theList = {} or theItem < 1 or theItem > (count theList) then
		error "Invalid Arguments"
		return
	end if
	
	-- filter out the first item since that's easy
	if theItem = 1 then
		return (items 2 through -1 of theList)
	end if
	
	-- similarly for the last item
	if theItem = (count of theList) then
		return (items 1 through -2 of theList)
	end if
	
	return ((items 1 through (theItem - 1) of theList) & (items (theItem + 1) through -1 of theList))
end removeItem

The idea here is that (after basic error checking on the parameters), you filter out the easy cases where the item to remove is the first or last item in the list.
If those cases fail and you need to remove an item from the middle, this script builds a new list consisting of items 1 through (i -1) of the original list (the items before the one to remove), and items (i+1) through the end of the list (to get the items after the one to be removed.

But this will only work for an ordinal list starting with 1!!! Not for a list of strings…

This routine from Emmanuel will return the index of the item in the list (no support for lists of lists/records):

on IndexOfItem(theItem, theList) -- credits Emmanuel Levy
	set text item delimiters to return
	set theList to return & theList & return
	set text item delimiters to {""}
	try
		-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
	on error
		0
	end try
end IndexOfItem

Easily adaptable to fit your needs:

set theList to {5, 8, 2, 56, 8}
set itemIndex to IndexOfItem(56, theList)

if itemIndex = theList's length then --> last item
	set finalList to items 1 thru -2 of theList
else if itemIndex = 1 then --> first item
	set finalList to rest of theList
else
	set finalList to items 1 thru (itemIndex - 1) of theList & ¬
		items (itemIndex + 1) thru -1 of theList
end if
--> {5, 8, 2, 8}

It wasn’t clear from the original post, but I assumed that when told to delete item 2 from the list, you want to delete the second item, no matter what its class or value, which is exactly what my script does… regardless of whether the item(s) in question are integers, strings, or any other AppleScript object.

Instead, you’re saying you want to delete the item whose value is passed into the routine, not whose index (nth item) is…

I probably should have read the original script a little closer.:slight_smile:

Nope! :oops:

You are rigth, Camelot… Seems that Mr. Nikel attempts to delete the second item, not the string “2”…

:oops: (again) :lol:

Ok people, this is what I wanted to do, sorry it wasn’t clear. Lets say I have a list of names in one list and I have a list of phone numbers in another. They are not in the same order (that means the first name does not correspond to the first number) but they somehow relate, so that because of ‘some property’ there’s only one name for each number and it’s one in particular. The idea is that the program searches the first list, takes a name (any), searches the second list and when it finds the correspondig number simply takes it out (and places it somewhere else or whatever, that doesn’t matter)


set beggings to {"please ","help me ","I can't figure this out."}
set lista_orig to {"Remove ", "any ", "of ", "these ", "words ", "please. ", "Even ", "if ", "it's ", 10 , " or ", 12} 

repeat with i from 1 to count of lista_orig
if (item i of lista_orig equals item k of beggings then set item_to_be_removed to i  -- the item to remove. k can be any number from the other list 
end repeat

remove_item(lista_orig,item_to_be_removed) --note that item_to_be_removed is a number, regardless of what the item contains.

--> should return {"Remove ", "any ", "of ", "these ", "words ", "Even ", "if ", "it's ", 10 , " or ", 12} 


Anyway, the question really was if there wasn’t any command to do that, like a


remove item i from the_list
or
set the_list to rest of item i of the list

If it’s the hard way… well, that one I figured out allready, hehe! BTW, this:


set the_new_list to items 1 thru (the_item -1) & items (the_item +1) thru -1) of the_list 


was very helpfull, I hadn’t thought it that way. Thanks a lot and if you should find a faster way to do it… your welcome to tell me!! 'til next time!