Finding objects in lists - python

I am making a function that has a list named possessions. I want a function to be able to find a given possession name and delete it from the list. I know how to delete things in python but I do not know the find.
So is there some type of:
find(list, object)
That returns the index of the objects?

>>> l = [1,2,3,4,5]
>>> l.remove(3)
>>> l
[1, 2, 4, 5]
Just use list.remove(<yourchoice>). However make sure that this will only remove the 1st matching item in case your list has multiple similar elements

Related

Removing earlier duplicates from a list and keeping order

I want to define a function that takes a list as an argument and removes all duplicates from the list except the last one.
For example:
remove_duplicates([3,4,4,3,6,3]) should be [4,6,3]. The other post answers do not solve this one.
The function is removing each element if it exists later in the list.
This is my code:
def remove(y):
for x in y:
if y.count(x) > 1:
y.remove(x)
return y
and for this list:
[1,2,1,2,1,2,3] I am getting this output:
[2,1,2,3]. The real output should be [1,2,3].
Where am I going wrong and how do I fix it?
The other post does actually answer the question, but there's an extra step: reverse the input then reverse the output. You could use reversed to do this, with an OrderedDict:
from collections import OrderedDict
def remove_earlier_duplicates(sequence):
d = OrderedDict.fromkeys(reversed(sequence))
return reversed(d)
The output is a reversed iterator object for greater flexibility, but you can easily convert it to a list.
>>> list(remove_earlier_duplicates([3,4,4,3,6,3]))
[4, 6, 3]
>>> list(remove_earlier_duplicates([1,2,1,2,1,2,3]))
[1, 2, 3]
BTW, your remove function doesn't work because you're changing the size of the list as you're iterating over it, meaning certain items get skipped.
I found this way to do after a bit of research. #wjandrea provided me with the fromkeys method idea and helped me out a lot.
def retain_order(arr):
return list(dict.fromkeys(arr[::-1]))[::-1]

How I can count the objects from a key of dictionary?

I have this dictionary (ignore the "Rank" key):
dict={
"asset": [("S3","A1"),"S2",("E4","E5"),("E1","S1"),"A6","A8"],
"Rank": lirank,
"number_of_attributes":
}
Ι want to count the objects of the "asset" key and add it to "number_of_attributes" as a list.
Τhe output that I want is :
"number_of_attributes":[2,1,2,2,1,1]
the values come from the first object of asset ("S3","A1") having 2 items, the second ("S2") having 1 item, etc.
I would ideally like to write it with a for loop but I am open to other ideas.
you can use a list comprehension:
my_dict["number_of_attributes"] = [1 if isinstance(x, str) else len(x) for x in my_dict["asset"]]
print(my_dict["number_of_attributes"])
output:
[2, 1, 2, 2, 1, 1]
First, consider naming your variables different than dict, list or tuple.
Second, a solution to this issue is already provided here:
https://codereview.stackexchange.com/questions/97217/deep-length-of-a-list
For your specific case:
myDict={"asset":[("S3","A1"),"S2",("E4","E5"),("E1","S1"),"A6","A8"], "Rank": lirank }
myDict["number_of_attributes"] = [len(itm) if isinstance(itm, tuple) else 1 for itm in myDict["asset"]]
print(myDict["number_of_attributes"])
Here is a link to an online python repl for your problem: https://repl.it/repls/SuperiorDisastrousMuse
There are answers above that provides you with a fix for your problem. However, the reason that you are in trouble with this is that you are mixing datatypes in the asset list. This is not typically a good idea, and your problem here is a good example of why.
Normally, if you had a list of items and you wanted the "length" or "number_of_attributes", as you need in this case, you would just want to be able to do something like:
number_of_attribues = [len(x) for x in dict['asset']]
But len(..) behaves differently for tuple and string, and for string it doesn't give you the value you want (1) but the count of letters in the string (2).
This happens because the asset list you have has items of different data types. This list:
asset = [("S3","A1"),"S2",("E4","E5"),("E1","S1"),"A6","A8"]
is a list of tuples and strings mixed. You can see this by looping through the list and printing the data type:
>>> for a in asset:
... print(type(a))
...
<class 'tuple'>
<class 'str'>
<class 'tuple'>
<class 'tuple'>
<class 'str'>
<class 'str'>
If you can change your asset list to use lists instead of tuples, then you'd have a much simpler solution. Like so:
If you can change your input list to contain items of the same type:
asset_as_list = [["S3","A1"],["S2"],["E4","E5"],["E1","S1"],["A6"],["A8"]]
You now have a list of lists. The tuples are now a list of two items (you call them attributes here) and the strings are now a list of one item.
This will give you two good things:
1) It will allow you to get your number_of_attributes in a much simpler way:
>>> number_of_attribues = [len(x) for x in asset_as_list]
>>> number_of_attribues
[2, 1, 2, 2, 1, 1]
2) You don't mix datatypes in your list, and it will be much easier to work with in other situations as well as making your code easier to understand and debug. Which will become more important as your codebase grows larger and larger.

How do i 'replace' an array by filling an empty array's elements using pop method from another array?

I'm trying to implement a stack in python and I'm experimenting with the list data structure. If i want to use the pop method to 'fill' an empty array by using the elements from an existing array, what do I do?
# Implementing Stacks in Python through the given list structure
practiceStack = []
practiceStack.append(['HyunSoo', 'Shah'])
practiceStack.append('Jack')
practiceStack.append('Queen')
practiceStack.append(('Aces'))
# printing every element in the list/array
for i in practiceStack:
print(i)
# since stacks are LIFO (last in first out) or FILO (first in last out), the pop method will remove the first thing we did
emptyArrayPop = []
This is what I tried (by using a for loop) and keep getting a use integers not list error
for i in practiceStack:
emptyArrayPop[i].append(practiceStack.pop)
print(emptyArrayPop)
The pop function is a function — not a value. In other words, practiceStack.pop is a pointer to a function (you can mostly ignore this until you've spent more time around code); you likely want this instead:
practiceStack.pop()
You also need to append to the list; when adding something with append, the List will automatically add it at the end; you do not need to provide an index.
Further explanation: The List.append method will take the value that you pass to it and add that to the end of the List. For example:
A = [1, 2, 3]
A.append(4)
A is now [1, 2, 3, 4]. If you try to run the following:
A[2].append(4)
...then you are effectively saying, "append 4 to the end of the value at position-2 in A", (`A[2] is set to 3 in the above example; remember that python lists start counting at 0, or are "0-index".) which is like saying "Append 4 to 3." This makes no sense; it doesn't mean anything to append an integer to another integer.
Instead, you want to append to the LIST itself; you do not need to specify a position.
Don't get this confused with assigning a value to a position in a List; if you were setting a value at an existing position of a list, you can use the = operator:
>>> B = [1, 2, 3]
>>> B[2]
3
>>> B[2] = 4
>>> print(B)
[1, 2, 4]
>>> B.append(8)
>>> print(B)
[1, 2, 4, 8]
So to answer your original question, the line you want is the following:
emptyArrayPop.append(practiceStack.pop())
(note the [i] has been removed)
[edit] Not the only issue, as #selcuk pointed out.
You will also need to fix the way you're accessing data in the practiceStack list, as you cannot edit a list (calling pop modifies the list in-place) when you are iterating over it.
You will need to iterate over the integer index of the list in order to access the elements of practiceStack:
for i in range(len(practiceStack)):
emptyArrayPop.append(practiceStack.pop())

sort a list in python by order of two other lists

I have an interesting problem for which I could not find any solution yet.
Having two lists with the same values in a different order. I reorder one list so, that the list gets identical. That's fine but I need to reorder also an additional third list with the same key.
I'm not able to use zip nor enumerate in my code to retrieve the new Index of the second list.
first=[(1,1,1),(2,2,2),(3,3,3)]
second=[(2,2,2),(3,3,3),(1,1,1)]
third=[2,3,1]
second=sorted(second,key=first.index)
print(second)
[(1,1,1),(2,2,2),(3,3,3)]
d = [i[0] for i in sorted(enumerate(second), key=lambda x:first.index)]
d should be (2,0,1) but it is not working
the goal for the third list is to become: [1,2,3]
To get [1, 2, 3], use:
third = sorted(third, key=list(map(lambda x: x[0],first)).index)
To get [2, 0, 1], use:
d = sorted(range(second), key=lambda x: first[x])
This question is solved.
One can fetch the index from re-ordered "second" as shown under the LINK, and use this indexlist to sort any other list.
Sort python list by order of another list AND retrieve old index

Make python set discard tuples with the same content, regardless of their order [duplicate]

I'm trying to make a set of sets in Python. I can't figure out how to do it.
Starting with the empty set xx:
xx = set([])
# Now we have some other set, for example
elements = set([2,3,4])
xx.add(elements)
but I get
TypeError: unhashable type: 'list'
or
TypeError: unhashable type: 'set'
Is it possible to have a set of sets in Python?
I am dealing with a large collection of sets and I want to be able to not have to deal duplicate sets (a set B of sets A1, A2, ...., An would "cancel" two sets if Ai = Aj)
Python's complaining because the inner set objects are mutable and thus not hashable. The solution is to use frozenset for the inner sets, to indicate that you have no intention of modifying them.
xx = set([])
# Nested sets must be frozen
elements = frozenset([2,3,4])
xx.add(elements)
People already mentioned that you can do this with a frozenset(), so I will just add a code how to achieve this:
For example you want to create a set of sets from the following list of lists:
t = [[], [1, 2], [5], [1, 2, 5], [1, 2, 3, 4], [1, 2, 3, 6]]
you can create your set in the following way:
t1 = set(frozenset(i) for i in t)
Use frozenset inside.
So I had the exact same problem. I wanted to make a data structure that works as a set of sets. The problem is that the sets must contain immutable objects. So, what you can do is simply make it as a set of tuples. That worked fine for me!
A = set()
A.add( (2,3,4) )##adds the element
A.add( (2,3,4) )##does not add the same element
A.add( (2,3,5) )##adds the element, because it is different!

Categories