Python3 objects passing from functions - class

The below code snippet is for deleting a node in linked list. My class contains two members namely data and next a pointer to hold other objects of that class type. When, I run my program, I don't get any error. If I try to delete the first item in the linked list, it enters the First for loop and displays the message "The data is found". But if I print my list, I am seeing the element in the list. I think this is because of assigning objects back, but I am not able to find where I have done that mistake. Any help is greatly appreciated.
def deleteNode(self, a_data):
flag = 0
if (self.data == a_data):
print("The data is found")
self = self.next
flag = 1
else:
while(self.next != None):
if (self.next.data == a_data):
self.next = self.next.next
flag = 1
break
else:
self = self.next
if(flag):
print("Data Deleted")
else:
print("Data not available")
Thanks

self = self.next in your code has no effect on the outside world: it just assigns to a local variable.
It looks like you are trying to delete a node from within Node class itself. You could use a function instead that accepts a list head and returns a (possibly new) list head with the corresponding item deleted:
def delete_node(head, data):
"""Delete the first node in the `head` list that has `data`."""
prev, node = None, head
while node is not None: # until the last node (`None` means empty list)
if node.data == data: # found node that has data
if prev is None: # we are at the very beginning of the list
assert head is node
head = node.next # remove the first node
else:
assert prev.next is node
prev.next = node.next # remove internal node
break
prev, node = node, node.next
return head

Friends,
I modified my function. I think the error may be because not assigning back the value to the original one, so I made my function to return value. Comments and other methods and any other reason for above than mine are cordially welcome.
def deleteNode(self, a_data):
flag = 0
if (self.data == a_data):
print("The data is found")
self = self.next
flag = 1
else:
while(self.next != None):
if (self.next.data == a_data):
self.next = self.next.next
flag = 1
break
else:
self = self.next
if(flag):
print("Data Deleted")
else:
print("Data not available")
return self
Thanks
S

Related

bug in the remove function in my LinkedList in swift

I am trying to implement a generic linkedList API like in Java in swift.This has been done probably in hundreds of ways but my question is not on how to do it rather, on what is wrong with a part of my logic when removing an item whose index is zero. I know, there are alternate ways to achieve what I want and I did that but I need to understand the flaw in a particular logic. please have a look.
I have following functions for now.
var size : Int { get } //give the size of the list
func add(_ value: Item) //add items to the list
func removeAt(index: Int) // removes the item from the specified index
func print() //prints the list
My logic flaw is in the remove(index:) method only when I try to remove an item from the beginning of the list(index=0). My logic is to set the head's next node to be the head if there are more than 1 item in the list(list.size>0).
The following is the full implementation-
import Foundation
class Node<Item>{
var value: Item
var next: Node?
init(value: Item) {
self.value = value
self.next = nil
}
}
class LinkedList<Item> {
var head: Node<Item>?
public init(){
self.head = nil
}
public init(_ value: Item){
self.head = Node(value: value)
}
private func isEmpty()->Bool{
if head == nil{
return true
}
return false
}
var size : Int {
guard var current = head else{
return 0
}
var count = 1
while current.next != nil {
guard let next = current.next else {
return count
}
count = count + 1
current = next
}
return count
}
func add(_ value: Item){
let node = Node(value: value)
if isEmpty(){
head = node
return
}
guard let head = head else {
return
}
var currentNode = head
while currentNode.next != nil {
guard let nextNode = currentNode.next else {
break
}
currentNode = nextNode
}
currentNode.next = node
}
func removeAt(index: Int) {
if isEmpty() || index >= self.size{
return
}
guard var last = head, var secondLast = head else{
return
}
// when index is zero and either the list has only one item or it has multiple items
if index == 0{ //here is the bug
if let next = last.next{
last = next
}else{
head = nil
}
return
}
var count = 0
while count < index{
guard let next = last.next else{
return
}
secondLast = last
last = next
count = count + 1
}
secondLast.next = last.next
}
func print(){
guard var current = head else {
return
}
if current.next == nil{ //if list contains only head
Swift.print(current.value)
return
}
while current.next != nil{
Swift.print(current.value)
guard let next = current.next else {
return
}
current = next
}
Swift.print(current.value)
}
}
Testing the code like -
let list = LinkedList<Int>()
for i in 0...5{
list.add(i)
}
list.print()
let index = 0
list.removeAt(index: index)
print("After removing..")
list.print()
Output:
1
2
3
4
5
After removing..
1
2
3
4
5
Can anyone please points out my fault.
The head of the list becomes the next item, if there is one. If the next item is nil, then the head of the list is also nil, like so:
if index == 0 { //here is the bug
head = head?.next
return
}
This code:
if let next = last.next{
last = next
}else{
head = nil
}
In the first branch, you return without changing "head", so the head of the list remains unchanged.
suppose head is at address 100
and the second item in the list is at address 200
let list = LinkedList<Int>()
list's head -> 100
in remove at index 0 we set last to head, and secondLast also to head
last -> 100[ |next -> 200]
secondLast -> 100[ |next -> 200]
then we say
if let next = last.next { last = next } return
Now last points to 200:
last -> 200[ |next -> 300]
But list's head hasn't changed
list's head -> 100[ |next -> 200]
secondLast -> 100[ |next -> 200]
Last goes out of scope, when we return, no changes to the list structure (in the heap) have happened.
In the working branch (where index > 0):
while count < index{
guard let next = last.next else{
return
}
secondLast = last
last = next
count = count + 1
}
secondLast.next = last.next
we go over the loop manipulating secondLast and last, and at some point we then reach the line
secondLast.next = ...
So then we actually assign to the object, we mutate the object in the heap, it's next pointer, we go from something like:
secondLast -> 100[ |next -> 200]
secondLast -> 100[ |next -> 300]
So now the list itself has changed, in the heap, the object at address e.g. 100 has a next pointer that is pointing to some object, e.g. at address 300.
Firstly, I really appreciate the time and effort #Shadowrun put into. However, the explanation still lack the reason as of why the code works when I am iterating the list and removing in between the list.
The reason is List itself only holds one pointer, head which is referring to an address in memory. Sure the last node points to the same address but when I try to update update the head (index = 0) with the help of last, last is points to a different address which means it deviates from head as soon as it leaves the scope. While list has no clue that there was a change and list still holds the same pointer to address as of before.
Now when I am iterating from head(index>0), the last is same as head and with each iteration the last moves forward to the next node. I change the next pointer of any node at anytime, the next pointer gets updated for that node successfully. Here the starting node is same as head as last and head is pointing to the same address. So, for iteration over the list, it doesn't matter whether I start with head or last, the chain linking is same. Here head and last is same at the beginning. But for index = 0, as list's head, itself needs to be changed, making last pointing to a different node won't work because list knows head and the head is not updated.
So, the real reason is the list has no clue of how the node's are inter-related with one exception and that is the head.
It's not about assigning object or anything else. It's about list pointing to only one node and that is head.

How to fetch objects from results one by one without do .count

I need to fetch from Realm Results 20 objects or less. A database can be heavy, so Results.count is a long time for calling.
So, what I need is to fetch objects from Results one by one until I get 20 or until last object.
But, when I'm trying to fetch index after the last object it's throwing Realm exception 'Index x is out of bounds (must be less than x)'.
So, this one isn't working:
let searchResult = Ticket().get(filter: "base == nil && deleted == 0 AND orderPaidAt > 0 AND (\(query))").sorted(byKeyPath: "orderPaidAt")
for i in 0..<20 {
if let ticket = searchResult[i] as? Ticket {
...
} else {
break
}
}
If I'm trying to use searchResult.count or searchResult.endIndex it increases a time a lot, especially on old devices. That's why I want to avoid it.
The results are lazily loaded, so you could loop through the results one by one, until the end, or until you hit a self-set count:
let searchResult = Ticket().get(filter: "base == nil && deleted == 0 AND orderPaidAt > 0 AND (\(query))").sorted(byKeyPath: "orderPaidAt")
var count = 0
for thisTicket in searchResult {
// do something
count += 1
if count > 20 { break }
}
This way you are only loading the values that you need, and never calling count or accessing the results out of bounds.
You can use prefix(maxLenght: Int) method to get a subCollection with specified maxLenght.
Example:
realm.objects(ObjectModel.self).prefix(20).count

LinkedList in Scala

For exercise I'm trying to implement a LinkedList in Scala.
Main problem is about Null reference.
But first some code:
class Node(xkey: String, xnext: Option[Node], xinfo: Int) {
val key: String = xkey;
var next = xnext.getOrElse(None);
var info: Int = xinfo;
def this(xkey: String, xinfo: Int) {
this(xkey, None, xinfo);
}
def this(xkey: String) {
this(xkey, None, -1);
}
#Override
override def toString: String = key + ":" + info
}
At this point, I'm already concerned about things.
I declare xnext in construct as a Option[Node], because the tail in this linkedList does not have a next.
In my first try, it was just a Node, but had problem with null object because compilator just told me that "null can't cast to Node" (or something like that, I do not remember now) - And so I switch to this Option.
But, is it ok? Because, you know, for me next should be a Node, not a Option, otherwise, I don't know, in the linkedList how to reference to next Node.
Whatever, second class (i.e. my Linked List)
class LinkedNode {
private var first: Option[Node] = None;
private var last: Option[Node] = None;
def addNode(newNode: Node) = {
if (first == null) {
first = Some(newNode);
last = Some(newNode);
first.next = last;
}
else {
last.next = newNode;
newNode.next = null;
last = newNode
}
}
def size(): Long = {
var currentNode : = first;
var size = 0L;
while (currentNode != null) {
size+=1;
currentNode = currentNode.next;
}
size
}
def findNodeByKey(key: String) : Node = {
var currentNode = first;
while(currentNode != null) {
if (currentNode.key.equals(key))
currentNode
else {
currentNode = currentNode.next;
}
}
currentNode;
}
def delNodeByKey(key : String) : Boolean = {
var currentNode = first;
var previousNode = first;
while(currentNode != null) {
if (currentNode.key.equals(key)) {
previousNode = currentNode.next;
return true;
}
previousNode = currentNode;
currentNode = currentNode.next;
}
return false;
}
}
And nothing. I'm already block to my constructor because first and last.
How should I declare them? Node? Or Option[Node]?
Problems are also in Add method.
When I add a node, I want to add a Node object, not an Option[Node].
And I don't get how to achieve things I want with all Option, Some and None classes.
I know I should not be so vague with my request, but any help?
P.S. I've already read this Q/A and it didn't help me
At this point, I'm already concerned about things. I declare xnext in construct as a Option[Node], because the tail in this linkedList does not have a next.
[...]
But, is ok? because, you know, for me next should be a Node, not a Option, otherwise, I don't know, in the linkedList how to reference to next Node.
This is a good solution to replacing null, which you definitely want to do to prevent null-pointer exceptions and the like. An Option[Node] is simply a Node wrapped in a container (or None). You can check whether or not it has a value with isEmpty or get its value with get (which will throw an exception if the Option is empty).
The only difference to null, as you'd use it in Java, is that you need to check if it isEmpty instead of checking for null, and that you need to unwrap (option.get) it explicitly when you're sure that it is not None.
A more paradigmatic (scala-typical) way of retrieving the value from an option is pattern matching:
option match {
case Some(x) => println(x)
case None => println("Whoops, no value :(")
}
Regarding your other questions, they are indeed a little vague.
How should I declere them? Node? or Option[Node]?
Use Option[Node] if the possibility exists that there's no value for the variable (i.e., if you'd set it to null sometimes in Java).
When I add a node, I want to add a Node object, not a Option[Node].
No, you want to add an Option[Node] internally, because you will need to check later on if a node is set or not. In Scala it is preferrable to do this via Option[Node].isEmpty compared to setting things to null. You're already doing this in some parts of your code (e.g., addNode), where you do Some(newNode) (I'd call this "wrapping the node in an Option", but I'm not entirely sure if that's the correct terminology).
And I don't get how to achieve things I want with all Option, Some and None class.
What you're doing in your addNode does seem correct to a degree, but you somehow try to use null again in the else branch. What about:
// We don't need Option[Node] for the parameter, because there
// _must_ be a Node value to be added
def addNode(newNode: Node) = {
if (first.isEmpty) {
first = Some(newNode)
last = Some(newNode)
first.next = last
} else {
newNode.next = None
last.next = Some(newNode)
last = Some(newNode)
}
}
(I didn't run that code, nor did I do an thorough check of your logic)

Calling a method in a class, in an if/elif statement

i'm creating trying to create a project, but i'm running into an error.
This is my code (not all of it, it's pretty lengthy, but the problem i'm running into):
class Rest(object):
def __init__(self, name, order=[], total=0):
self.name = name
self.order = []
self.total = 0
def end_order(self):
print("Here is your complete order: {0}".format(self.order))
print("Here is your total: {0}".format(self.total))
def order_menu(self):
loop = 1
while (loop == 1):
question_1 = raw_input("What would you like? Push S to Submit, Push C to Cancel")
if (question_1 == "1"):
self.total += 4.99
print("You added a cheeseburger, $4.99)
elif (question_1 == "S"):
end_order()
Okay, so under order_menu(self), under the elif statement, it gives me an error:
"Global name 'end_order()' is not defined".
There's a probably something silly i'm not doing, but I can't figure out what..
I believe the self keyword is required in Python when calling a class method. Try:
self.end_order()

Lua custom linked list for class creation practice fails to set node.next

So I've been trying to figure out how to mimic classes in lua. So I could start with some basic code that I already have written in other languages, I started with a linked list. I have what seems to be a working node class, but when i try to print out the list from my LList class, I cant seem to get it to print.
There seems to be a problem where after the first node is added to the list, either the second node that is added gets overwritten by the third, or it simply doesn't actually get added. This could be a problem with a while loop I'm using, but I have no idea why it would be an issue in this case.
Here is the Linked List "class"
LList = {}
LList.__index = LList
function LList.create()
local list = {} -- our new object
setmetatable(list,LList) -- make LList handle lookup
list.count = 0 -- initialize our object
list.head = nil
return list
end
function LList:add(newNode)
print("DEBUG PRINT: LList:add(): newNode.data: "..newNode:getData().." LList.count: "..self.count)
if(self.head) then
local curr = self.head
print("DEBUG PRINT: LList:add(): self.head:toString(): "..self.head:toString())
print("DEBUG PRINT: LList:add(): curr:toString(): "..curr:toString())
print("DEBUG PRINT: LList:add(): newNode:toString: "..newNode:toString())
while curr.nextNode do --this is the while loop in question
print("DEBUG PRINT: LList:add(): in while:"..curr:toString())
curr = curr.nextNode
end
curr:setNext(newNode)
print("DEBUG PRINT: LList:add(): curr.nextNode:toString(): "..curr.nextNode:toString())
self.count = self.count + 1
else
self.head = newNode
self.count = 1
print("DEBUG PRINT: LList:add(): self.count" .. self.count .." self.head:getData(): ".. self.head:getData())
end
print("DEBUG PRINT: LList:add(): EXITING\n")
end
function LList:getLen()
return self.count
end
function LList:toString()
print("Stubbed toString()")
if(head)then
print(self:toStringHelper(head))
else
print("emptyList")
end
end
function LList:toStringHelper(currNode)
if(currNode.nextNode)then
return currNode:toString() .. toStringHelper(currNode.nextNode)
else
return currNode:toString()
end
end
This here is the Node "class"
Node = {}
Node.__index = Node
function Node.create(newData)
local tNode = {}
setmetatable(tNode, Node)
tNode.data = newData
return tNode
end
function Node:getData()
return self.data
end
function Node:getNext()
return self.nextNode
end
function Node:setNext(newNode)
self.nextNode = newNode
print("DEBUG PRINT: Node:setNext(): self.nextNode:toString(): "..self.nextNode:toString())
end
function Node:hasNext()
if self.nextNode then
return true
else
return false
end
end
function Node:toString()
return tostring(self.data)
end
This is the tester code. Again, all code is in one file for ease of testing.
testerList = LList.create()
print(testerList:getLen())
tNode1=Node.create(5)
tNode2=Node.create(7)
tNode3=Node.create(2)
testerList:add(tNode1)
testerList:add(tNode2)
testerList:add(tNode3)
print(testerList:getLen())
print(testerList:toString())
I believe that my problem is either in the while loop implementation, or in the way I'm setting the Node.nextNode data.
Works for me after fixing some typos in your code:
In LList:toString() you need to replace the references to head with self:head and in LList:toStringHelper(currNode) you need to replace the references to toStringHelper with self:toStringHelper. After this the code prints out the correct list.