Object Oriented Programming removing repeated items (Python) - python

I'm trying to remove an item from a sorted list. If the item is not in the list, then the list remains unchanged. If the item occurs multiple times, only one occurrence of the item is removed. Again, I'm not allowed to use build-in list functions, but for the time being, I'm just trying to get the code to just work!
class SortedList:
def __init__(self):
self.s_list = []
def insert(self, item):
self.s_list.append(item)
def remove(self, item):
finalSet=[]
for item in self.s_list:
if item not in finalSet:
finalSet.append(item)
return finalSet
def __str__(self):
return str(self.s_list)

Your remove function seems very confused.
def remove(self, item):
finalSet=[]
for item in self.s_list:
if item not in finalSet:
finalSet.append(item)
return finalSet
Why are you creating a new list, shouldn't you be modifying the existing list?
There are two different item in the function. One is a parameter to the function, the other is in the loop. The one in the loop replaces the parameter. Give them different names
You return with the list almost right away, you probably don't want to return until after the loop is completed. Your return statement is intended too far
Since you've confused two different variables by giving them the same name, I can't guess what you were actually trying to do inside the loop.

Other Question
Full page about topic

Related

Dynamic Generator in Python

I need to create a service that can manage a dynamic resource (I'm thinking on a dynamic csv that is growing. In this case I used a list to make more easy to understand), returning the next item from an iterable.
If the list is finished, the output would be False and I need to wait that an element is added.
When the element if finally added, the generator should yield the new added item (this is the part that I can not understand how to do).
a_lst = [1, 2]
class DynamicGenerator:
"""
Generic Generator that return item by item from a_lst and
can append a new item when needed.
"""
def __init__(self):
global a_lst
def gen_lst(self):
for item in a_lst:
yield item
def grow_lst(self, new_item):
a_lst.append(new_item)
class AvailableNextIterator:
"""
Return next item from iterable if it's available,
else return False.
"""
def __init__(self, iterable):
self.iterator = iterable
def __next__(self):
return next(self.iterator, False)
dg = DynamicGenerator()
gl = dg.gen_lst()
it = AvailableNextIterator(gl)
print(it.__next__())
print(it.__next__())
print(it.__next__())
dg.grow_lst(3)
print(it.__next__())
This is the code output:
1
2
False
False
This is the output that I need:
1
2
False
3
Very simply, you exhausted the iteration before you added the last item; you already tripped the end-of-data exception for gen_list. You've dropped out of the loop, and there's no provision to re-enter. You can see this with a little simple tracing in that method:
def gen_lst(self):
for item in a_lst:
yield item
print("gen_lst is out of data")
yield "over the cliff's edge ..."
Now, the output is
1
2
gen_lst is out of data
over the cliff's edge ...
False
You seem to want a FIFO queue; I suggest that you use the available data structure in the readily-available packages, rather than trying to roll your own.
However, if this is a homework exercise:
Mark your question as such, as required by SO posting standards;
Research existing implementations.
Maintain the queue as an attribute of the instance, not an external variable. Your "generator" should check the queue directly, rather than depending on for to manage the iteration.

Error when using __iter__ and __next__ with a Python linked list? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
def __iter__(self):
return self
def __next(self):
if self.head is None:
raise StopIteration
else:
return self.head.next
Basically I attempted these implementation of the methods based on a basic example for W3 schools. It doesn't like that iter is returning an object type of the LinkedList.
Error:
TypeError: iter() returned non-iterator of type 'LinkedList' linked list
If I try to return self.head, it doesn't like that it is a node object?
Error:
TypeError: iter() returned non-iterator of type 'Node'
I am trying to make my LinkedList iterable with a forloop, but am having a hard time.
Does anyone know the correct implentation to make a LinkedList iterable in Python? Similar questions on here do not make sense to me and the solutions don't work for my usage.
The dunder method for the next item is __next__ rather than __next, and you seem to be missing code that actually moves through the list as you iterate.
The normal method I use is to have a separate iterator class within the type to do the grunt work. In addition, the way you have your list set up makes the idea of an element class desirable as well (were you using a Python list, this would not be needed but, since you want an item and next "pointer", it's better as a separate class).
Let's start by creating the list class with an enclosed item class:
class MyList:
# Single element in the list.
class MyListElem:
def __init__(self, item, link_from = None, link_to = None):
# Set data, link from previous and to next if specified.
self._item = item
self._next = link_to
if link_from is not None:
link_from.change_link(self)
def change_link(self, item):
self._next = item
The element class has two methods, the first creating an element with links as needed. At the moment (see MyList.add() below), the to link is always None as we only append to the list.
Similarly, the from link is either None or the current tail, depending on whether we're adding the first or subsequent elements to the list.
These parameters are mostly here to cater for the possibility of later being able to insert at arbitrary places in the list.
Next is the iterator class, also part of the list class:
# Iterator over the list.
class MyListIter:
def __init__(self, head):
# Start at the head.
self._curr = head
def __iter__(self):
# To iterate over the iterator rather than collection.
return self
def __next__(self):
# Check more left, advance to next and return current.
if self._curr is None:
raise StopIteration
ret_val = self._curr._item
self._curr = self._curr._next
return ret_val
This is relatively simple, the initialiser just sets us up so that the first call will return the head. The __iter__ call allows you to retrieve an iterator from the collection and then iterate over that, rather than iterating directly over the collection. The difference being:
for iter in object: # iterate over object
pass
iter = object.__iter__() # iterate over iterator
for iter2 in iter:
pass
See here for more details on why this may be necessary.
The __next__ call is the "meat" of the iterator. It raises an exception if the iterator is finished. Otherwise it returns the current value, after advancing to the next.
And then the list class itself, a very simple one that only allows appending to the end, no deleting, and an iterator to process it:
# The list itself.
def __init__(self):
# Empty list to start with.
self._head = None
self._tail = None
def add(self, val):
# Append to the end of the list.
if self._head is None:
self._head = self.MyListElem(val)
self._tail = self._head
else:
self._tail = self.MyListElem(val, self._tail)
def __iter__(self):
return self.MyListIter(self._head)
It's really that easy (well, relatively easy). The following test code shows it in action:
x = MyList()
x.add(12345)
x.add(42)
x.add("Hello")
x.add([1, 2, 3])
for i in x:
print(i)
The output of that is, as expected:
12345
42
Hello
[1, 2, 3]

copy from a list to another list with append() in python

i need to copy a some member of my list to a new list without removing from original list.
i do this with append.
see my code :
def add_citizens(self, value):
for i in value:
i.colony = self
self.citizens.append(i)
actually after for loop , i removed from value list!
can any person say to me that copying with append is true? or there is a better way?
Thanks a lot
You could simply add to the citizens list using this code:
class Citizens:
def __init__(self):
self.citizens = []
def add_citizens(self, value):
for i in value:
self.citizens.append(i)
citizenClass = Citizens()
citizenClass.add_citizens(["Add", "Some", "Citizens"])

Fixing My Base 10 to Binary Converter

Right now, I have a base 10 to base 2 converter that works, however it always prints none at the end of every conversion.
base_two=0
def binary_recursion(base_ten):
global base_two
if base_ten==0:
print(base_two)
return
c=0
while base_ten//2**c>1:
c+=1
base_two+=10**c
if c==0:
print(base_two)
return
binary_recursion(base_ten-2**c)
I tried returning base_two as opposed to printing it, but that doesn't return a number, it also just returns None. Can anyone help me pinpoint my mistake?
def node(document_info, next_node):
return {'data': document_info, 'next': next_node}
def insert(head, new_document_info):
#insert new document into the linked list head
#returns the head of the modified list
if head is None:
return node(new_document_info, None)
if new_document_info[1] <= head['data'][1]:
return node(new_document_info, head)
head['next'] = insert(head['next'], new_document_info)
return head
Here's a slightly modified way of doing insertion sort, from my answer to you last question. You would start with head = None and then every time you add a print job do head = insert(head, document_info). Or after collecting all of your print jobs do something like
head = None
for document_info in list_queue:
head = insert(head, document_info)
You are not adding new element into queue. Assuming list_queue is a queue.
Queue has put function to add a new element into it.
def make_job():
temp_list=[]
list_queue = Queue()
for line in print_list:
if line[:6]=='submit': #If the command is submit, then the file must be placed in its
a=line.split() #correct spot in the linked list
del(a[0])
list_queue.put(a)#Contains file id, and the time required to print
temp_list.append(list_queue)
organize(list_queue) #Places the file in its correct spot in the linked list
else:
break
The Python queue module has a class called PriorityQueue that does exactly what you're looking for. For your situation, using it would look something like this:
class Job(object):
def __init__(self, name, print_time):
self.name = name
self.print_time = print_time
def __lt__(self, other):
return self.print_time < other.print_time
import queue as _queue # Need to rename the module so it doesn't conflict with your 'queue' function
my_queue = _queue.PriorityQueue()
def make_job():
for line in print_list:
if line[:6]=='submit':
a=line.split()
del(a[0])
new_job=queue(a) # queue(a) now returns a Job, e.g. Job('101', 40), instead of a 2-element list
my_queue.put(new_job)
else:
break
Once my_queue has been constructed, then repeated calls to my_queue.get() will return the Jobs ordered by print_time.
If you want to be able to inspect the contents of the queue without removing elements (get removes the element it returns), you could append the Jobs to a list and call list_queue.sort() after every insertion. If this is a performance concern, you could find the right spot in the list yourself and call list_queue.insert(i, a). Deferring to Python's list.sort has some advantages, though; namely, it's stable.
Lastly, if you don't want to define a new class, you could use sorted or list.sort with a custom sorting function. This takes the place of the __lt__ member I defined for Job.
new_job=queue(a) # queue(a) is your original function, which returns 2-element lists like ['101', 40]
list_queue.append(new_job)
list_queue.sort(key=lambda a,b: return a[1]<b[1])

Binary Searching and lists

class BinaryStringList():
def __init_(self):
self.item = []
def strAdd(self,item):
self.items.append(item)
def finditem(self, item):
if len(self)==0:
print("List is empty!")
else:
midpoint = len(self)//2
if self[midpoint]==item:
print("Item Found ", item)
else:
if item<self[midpoint]:
return finditem(self[:midpoint], item)
else:
return finditem(self[midpoint+1:], item)
So where I am finding I have an issue is when trying to add items to the list. If i do something like:
alist = BinaryStringList()
alist.strAdd("test1")
my code fails stating object has no attribute. Not sure why it is failing since I have almost the exact same code for another program except the find is using a sequential search where as this is a binary search.
You have multiple syntax errors in your code. Also recursion doesn't work that way, you need to have a base condition which returns. This solution will work, but I strongly suggest you to solve simpler problems using recursion to understand how it works.
class BinaryStringList:
def __init__(self): # You had 1 _ after init
self.items = [] # Typo, should have been items.
def strAdd(self,item):
self.items.append(item)
def finditem(self, item):
return self.binser(self.items, item)
def binser(self, items, item):
if len(items)==0:
return
midpoint = len(items)/2 # len(self) means nothing, it should be len(self.items)
if items[midpoint]==item:
return item
else:
if item<items[midpoint]:
return self.binser(items[:midpoint], item) #self[:midpoint] means nothing, you needed self.items[:midpoint]
else:
return self.binser(items[midpoint+1:], item)
binser = BinaryStringList()
binser.strAdd(1) # You added a string here. Your logic won't work with string.
binser.strAdd(2)
binser.strAdd(3)
binser.strAdd(5)
binser.strAdd(8)
binser.strAdd(9)
binser.strAdd(10)
print binser.finditem(1)
print binser.finditem(10)
print binser.finditem(5)
print binser.finditem(11)
(there are other ways of solving binary search too - i.e. iterative approach, passing low/high index values rather than splicing the input array). Try to solve binary search using those two approaches.
Binary search with passing low/high index values, your signature for binser will look like: def binser(self, low, high, item):
Your code is failing because you misspelled __init__. You need two underscores on each side, or it's just a weirdly named method. Since you lack a __init__, the default __init__ (which sets no attributes) is used, and you don't have an item or items attribute. You need to fix the __init__, and use a consistent name for items:
class BinaryStringList():
def __init__(self): # <-- Added extra trailing underscore
self.items = [] # Fixed name to be items, not item
You have many other problems here (you're not maintaining sorted order, so binary search won't work, you haven't implemented __getitem__ so self[midpoint] won't work so you'd need self.items[midpoint], lack of __len__ means len(self) won't work either, etc.), but the two issues above are what specifically makes you get the AttributeError.

Categories

Resources