Assign a object to the pointer the node is referring - python-3.4

class BinarySearchTree:
def __init__(self, value=None, left=None, right=None):
self.value = value
self.left = left
self.right = right
def insert(self, value) -> bool:
current_node = self
while current_node is not None:
if current_node.value < value:
current_node = current_node.left
elif current_node.value == value:
return False
elif current_node.value > value:
current_node = current_node.right
# id(current_node) <-- I need to create a object on this
current_node = BinarySearchTree(value) # <--
# id(current_node) <-- This is a new assigned id, but I need the same as the previous id
return True
binary_search_tree = BinarySearchTree(2)
binary_search_tree.insert(5)
print(binary_search_tree.__dict__)
current_node refers to current_node.left or current_node.right.
I need to create a new object and assign it to the pointer the current_node is referring,
but I only create a new object and assign it to a new pointer.

a new assigned id, but I need the same as the previous id
After the loop, as Scott Hunter noted, current_node is None, so the previous id is the “identity” of None, and you surely understand that a new object's id cannot be the same as the id of None. What you could do is modify the loop in a way which allows to refer to the attribute left or right afterwards as needed:
while current_node is not None:
object = current_node # remember the node to be changed
if current_node.value < value:
current_node = current_node.right
name = 'right' # remember the attribute to be changed
elif current_node.value == value:
return False
elif current_node.value > value:
current_node = current_node.left
name = 'left' # remember the attribute to be changed
setattr(object, name, BinarySearchTree(value)) # make the change
Alternatively you could make things a bit more simple by replacing in __init__
self.left = left
self.right = right
with
self.subtree = [left, right]
and the whole body of insert with
if value == self.value: return False
t = 0 if value < self.value else 1
if self.subtree[t]: return self.subtree[t].insert(value)
self.subtree[t] = BinarySearchTree(value)
return True

Related

Eliminate the empty spaces in QAbstractTableModel item when cell is checkable

I am trying to implement a custom QTableView. For that I am subclassing QAbstractTableModel such that it takes a list of strings. Here the implementation.
class ListTableModel(qtc.QAbstractTableModel):
def __init__(self, data: List[List[str]], headers: List[str] = None, edit: List[Union[int, Tuple[int, int]]] = None,
checks: List[Union[int, Tuple[int, int]]] = None, *args, **kwargs):
super().__init__(*args, **kwargs)
self._data = data
self._headers = headers
self._edit = edit
self._checks = checks
self._check_state = {}
self.name = None
def get_name(self):
return self.name
def set_name(self, name: str):
self.name = name
def check_state(self, value, index):
if index in self._check_state:
return self._check_state[index]
else:
if value == 0:
return qtc.Qt.Unchecked
else:
return qtc.Qt.Checked
def data(self, index, role):
if index.isValid() or (0 <= index.row() < self.rowCount() and 0 <= index.column() < self.columnCount()):
val = self._data[index.row()][index.column()]
val = fast_real(val, coerce=False)
if (
role == qtc.Qt.DisplayRole or role == qtc.Qt.EditRole) and not index.flags() & qtc.Qt.ItemIsUserCheckable:
if isinstance(val, float):
return f"{val:.4f}"
return str(val)
if role == qtc.Qt.CheckStateRole and index.flags() & qtc.Qt.ItemIsUserCheckable:
return self.check_state(val, index)
return None
return None
def setData(self, index, value, role):
if role == qtc.Qt.EditRole:
val = fast_real(value, coerce=False)
self._data[index.row()][index.column()] = val
return True
if role == qtc.Qt.CheckStateRole:
self._check_state[index] = value
return True
return False
def flags(self, index):
if self._edit is not None and index.column() in self._edit:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled
if self._edit is not None and (index.row(), index.column()) in self._edit:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled
if self._checks is not None and index.column() in self._checks:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled | qtc.Qt.ItemIsUserCheckable
if self._checks is not None and (index.row(), index.column()) in self._checks:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled | qtc.Qt.ItemIsUserCheckable
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled | qtc.Qt.ItemIsEditable
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0])
def headerData(self, section, orientation, role):
if role == qtc.Qt.DisplayRole:
if orientation == qtc.Qt.Horizontal and self._headers is not None:
return str(self._headers[section])
The class takes a list of list containing strings (representing the table). A list of strings representing the headers of the columns. The optional arguments edit and checks define which columns (if given as int) or cells (if given as tuple) are editable and checkable. The underlying data structure data takes values of 0 if the corresponding checkbox is unchecked, or any other value if the corresponding checkbox is checked.
My first question is that the cells that are checkable actually show some extra space, apart from drawing the checkbox. A separating line in the middle of the cell is actually visible when selecting the cell. How can I eliminate this? In the data method I control for cells that are checkable, and skip the display of the underlying data if it is. So I do not know how else to proceed here.
EXTRA: I would like to capture the signal that the model emits when any of the checkboxes are checked/unchecked. Any hint on this would be much appreciated as well.

wxPython: populate grid from another class using flatenotebook

I am trying to save a text file from the first page of a flatNotebook, write them to an EXTERNALLY defined sqLite database and write the values to a grid on the second page of the flatNotebook. The values are saved to the text file and written to the database successfully but I cannot get the values to populate the grid at the same time. They values show up in the grid after I close the program and restart it. I am having a hard time understanding how to call the function onAddCue(). I have tried so many things that I'm just confusing myself at this point. Please help me understand what I am doing wrong. Here is my entire code:
cue =[4,'NodeA',11,22,33,44,55,66,77,88,99]
class InitialInputs(scrolled.ScrolledPanel):
global cue
def __init__(self, parent, db):
scrolled.ScrolledPanel.__init__(self, parent, -1)
self.db = db
self.cur = self.db.con.cursor()
self.saveBtn = wx.Button(self, -1, "Save Current Values")
self.Bind(wx.EVT_BUTTON, self.onSave, self.saveBtn)
self.dirname = ""
def onSave(self, event):
global cue
dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.txt", wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_OK:
itcontains = cue
self.filename=dlg.GetFilename()
self.dirname=dlg.GetDirectory()
filehandle=open(os.path.join(self.dirname, self.filename),'w')
filehandle.write(str(itcontains))
filehandle.close()
dlg.Destroy()
row = cue[0] - 1
InsertCell ="UPDATE CUES SET 'Send'=?,'RED'=?,'GREEN'=?,'BLUE'=?,'RGB_Alpha'=?,'HUE'=?,'SAT'=?,'BRightness'=?,'HSB_Alpha'=?,'Fade'=? WHERE DTIndex=%i" %row
self.cur.execute(InsertCell, cue[1:])
self.db.con.commit()
GridPanel().grid.onAddCue() #This is the part that's not working
class Grid(gridlib.Grid):
global cue
def __init__(self, parent, db):
gridlib.Grid.__init__(self, parent, -1)
self.CreateGrid(20,10)
for row in range(20):
rowNum = row + 1
self.SetRowLabelValue(row, "cue %s" %rowNum)
self.db = db
self.cur = self.db.con.cursor()
meta = self.cur.execute("SELECT * from CUES")
labels = []
for i in meta.description:
labels.append(i[0])
labels = labels[1:]
for i in range(len(labels)):
self.SetColLabelValue(i, labels[i])
all = self.cur.execute("SELECT * from CUES ORDER by DTindex")
for row in all:
row_num = row[0]
cells = row[1:]
for i in range(len(cells)):
if cells[i] != None and cells[i] != "null":
self.SetCellValue(row_num, i, str(cells[i]))
self.Bind(gridlib.EVT_GRID_CELL_CHANGED, self.CellContentsChanged)
def CellContentsChanged(self, event):
x = event.GetCol()
y = event.GetRow()
val = self.GetCellValue(y,x)
if val == "":
val = "null"
ColLabel = self.GetColLabelValue(x)
InsertCell = "UPDATE CUES SET %s = ? WHERE DTindex = %d"%(ColLabel,y)
self.cur.execute(InsertCell, [(val),])
self.db.con.commit()
self.SetCellValue(y, x, val)
class GridPanel(wx.Panel):
def __init__(self, parent, db):
wx.Panel.__init__(self, parent, -1)
self.db = db
self.cur = self.db.con.cursor()
grid = Grid(self, db)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(grid)
self.SetSizer(sizer)
self.Fit()
def onAddCue():
global cue
row = cue[0] - 1
col=0
while col < 10:
for i in cue[1:]:
grid.SetCellValue(row, col, str(i))
col = col+1
class GetDatabase():
def __init__(self, f):
# check db file exists
try:
file = open(f)
file.close()
except IOError:
# database doesn't exist - create file & populate it
self.exists = 0
else:
# database already exists - need integrity check here
self.exists = 1
self.con = sqlite.connect(f)
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,"Stage Lighting", size=(800,600))
panel = wx.Panel(self)
notebook = wx.Notebook(panel)
page1 = InitialInputs(notebook, db)
page2 = GridPanel(notebook, db)
notebook.AddPage(page1, "Initial Inputs")
notebook.AddPage(page2, "Grid")
sizer = wx.BoxSizer()
sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5)
panel.SetSizer(sizer)
self.Layout()
if __name__ == "__main__":
db = GetDatabase("data.db")
app = wx.App()
logging.basicConfig(level=logging.DEBUG)
Frame().Show()
app.MainLoop()
Apparently, the question is about python syntax errors!
onAddCue is a method belonging to the class GridPanel. The class is instantiated in the variable page2.
So, you need to call the method something like this:
page2.OnAddCue()

How can I create new map with new values but same keys from an existing map?

I have an existing map in Groovy.
I want to create a new map that has the same keys but different values in it.
Eg.:
def scores = ["vanilla":10, "chocolate":9, "papaya": 0]
//transformed into
def preference = ["vanilla":"love", "chocolate":"love", "papaya": "hate"]
Any way of doing it through some sort of closure like:
def preference = scores.collect {//something}
You can use collectEntries
scores.collectEntries { k, v ->
[ k, 'new value' ]
}
An alternative to using a map for the ranges would be to use a switch
def grade = { score ->
switch( score ) {
case 10..9: return 'love'
case 8..6: return 'like'
case 5..2: return 'meh'
case 1..0: return 'hate'
default : return 'ERR'
}
}
scores.collectEntries { k, v -> [ k, grade( v ) ] }
Nice, functional style solution(including your ranges, and easy to modify):
def scores = [vanilla:10, chocolate:9, papaya: 0]
// Store somewhere
def map = [(10..9):"love", (8..6):"like", (5..2):"meh", (1..0):"hate"]
def preference = scores.collectEntries { key, score -> [key, map.find { score in it.key }.value] }
// Output: [vanilla:love, chocolate:love, papaya:hate]
def scores = ["vanilla":10, "chocolate":9, "papaya": 0]
def preference = scores.collectEntries {key, value -> ["$key":(value > 5 ? "like" : "hate")]}
Then the result would be
[vanilla:like, chocolate:like, papaya:hate]
EDIT: If you want a map, then you should use collectEntries like tim_yates said.

Add widget to Qsqlquerymodel

I want to add a column of checkboxes to a Qsqlquerymodel. The checkboxes are not linked to the data base. Using delegates seems much to low level for what I am trying to do.
The code I would like to use would be based on (PyQt) :
model = QtSql.QSqlQueryModel()
model.insertColumn(2) #checkbox column
checkboxes = list() #Used later to check checkboxe state
for i in range(0, model.rowCount()):
checkboxes.append((i, QtGui.QCheckBox())) #store row and checkbox in list
model.addWidget(i, 2, checkboxes[-1][1]) #addWidget in row(i), col(2) does not exist :(
Is it possible not to use delegates so the code is simpler?
Should I use layouts and not include the checkboxes in the model?
Am I missing a simple solution?
I mangaed by subclassing QsqlQueryModel following Sibylle Koczian work.
class CheckboxSqlModel(QtSql.QSqlQueryModel):
def __init__(self, column):
super(CheckboxSqlModel, self).__init__()
self.column = column
self.checkboxes = list() #List of checkbox states
self.first = list() #Used to initialize checkboxes
#Make column editable
def flags(self, index):
flags = QtSql.QSqlQueryModel.flags(self, index)
if index.column() == self.column:
flags |= QtCore.Qt.ItemIsUserCheckable
return flags
def data(self, index, role=QtCore.Qt.DisplayRole):
row = index.row()
if index.column() == self.column and role == QtCore.Qt.CheckStateRole:
#Used to initialize
if row not in self.first :
index = self.createIndex(row, self.column)
self.first.append(row)
self.checkboxes.append(False)
return QtCore.Qt.Unchecked
#if checked
elif self.checkboxes[row]:
return QtCore.Qt.Checked
else:
return QtCore.Qt.Unchecked
else:
return QtSql.QSqlQueryModel.data(self, index, role)
def setData(self, index, value, role=QtCore.Qt.DisplayRole):
row = index.row()
if index.column() == self.column and role == QtCore.Qt.CheckStateRole:
if value.toBool():
self.checkboxes[row] = True
else:
self.checkboxes[row] = False
self.dataChanged.emit(index, index)
return True
else:
return False

Groovy Collections: count weirdness with Strings

I am trying to count string values in a member of an object. I have tried three ways, but only one works. I am fine with the one that works, but I can't understand why the others fail. Here's the code:
void testCount() {
TestObj a = new TestObj()
TestObj b = new TestObj()
TestObj c = new TestObj()
a.s = "one"
b.s = "two"
c.s = "two"
def list = [a, b, c]
def count = 0
list.each{
if (it.s.equals("two"))
count++
}
assertTrue("each test failed", count == 2)
assertTrue("collectAll test failed", list.collectAll{ it.s.equals("two")}.size() == 2)
assertTrue("count test failed", list.count{ it.s.equals("two")} == 2)
}
I would expect the Closures passed to collectAll and count to do the same thing I'm doing in my each method. But in the case of collectAll it returns all 3 of the objects and in the case of count it always returns 0.
What am I missing?
collectAll is recursively going through your list, and returning a boolean (as that is what your closure returns for each element in the List)...
So, you get [ false, true, true ], which has 3 elements...
For count,
list.count{ it.s == "two" }
Returns 2 (as expected)
btw: you can do it.s == 'two' in groovy.. no need for all the .equals( "two" )
Edit... Example for count:
class TestObj {
String s
}
list = [ new TestObj( s:'one' ), new TestObj( s:'two' ), new TestObj( s:'two' ) ]
println( list.count { it.s == 'two' } )
Prints 2 for me...
edit 2
Found the cause (from comment below), count didn't accept a closure as a parameter till 1.8 so you'll be calling the object version which will tell you how many times an instance of the closure exists in the list (which is none, as it says)

Resources