I was trying to merge two binary trees and if I use "return root;" at last, the system told me "error: cannot find symbol: variable root". It works when I add "return root;" to every conditions. I don't understand why. Furthermore, in my past experience, it seems I don't have to write return statements after recursion function calls. Can someone explain this? Thank you!
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) {
return null;
}
else if (t1 == null) {
TreeNode root = new TreeNode(t2.val);
root.left = mergeTrees(null, t2.left);
root.right = mergeTrees(null, t2.right);
}
else if (t2 == null) {
TreeNode root = new TreeNode(t1.val);
root.left = mergeTrees(t1.left, null);
root.right = mergeTrees(t1.right, null);
}
else {
TreeNode root = new TreeNode(t1.val + t2.val);
root.left = mergeTrees(t1.left, t2.left);
root.right = mergeTrees(t1.right, t2.right);
}
return root;
}
Your variable root is declared inside your if, else if, and else statements, therefore it loses scope once you get to the return outside your if statement block. If you want to return root, I would suggest this.
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
TreeNode root; //Declare it here so it doesn't lose scope
if (t1 == null && t2 == null) {
return null;
}
else if (t1 == null) {
root = new TreeNode(t2.val);
root.left = mergeTrees(null, t2.left);
root.right = mergeTrees(null, t2.right);
}
else if (t2 == null) {
root = new TreeNode(t1.val);
root.left = mergeTrees(t1.left, null);
root.right = mergeTrees(t1.right, null);
}
else {
root = new TreeNode(t1.val + t2.val);
root.left = mergeTrees(t1.left, t2.left);
root.right = mergeTrees(t1.right, t2.right);
}
return root;
}
Unless you are programming in JavaScript and use var the variables in most algol languages has block scope.. Thus:
{ // new block scope started
TreeNode root = new TreeNode(t2.val); // New variable TreeNode created
} // Everything created in this scope gets destroyed
root; // Would no compile as root is an unbound variable
If you want to create a variable to be returned you need to create it in the same scope as you return. Thus:
{
TreeNode root = null;
// .. you logic goes here
return root;
} // root goes out of scope here
Trivia: I mentioned JavaScript and in that language using var your code would work:
function mergeTrees(t1, t2) {
if (t1 === null && t2 === null) {
return null;
}
else if (t1 === null) {
var root = new TreeNode(t2.val);
root.left = mergeTrees(null, t2.left);
root.right = mergeTrees(null, t2.right);
} else if (t2 === null) {
var root = new TreeNode(t1.val);
root.left = mergeTrees(t1.left, null);
root.right = mergeTrees(t1.right, null);
} else {
var root = new TreeNode(t1.val + t2.val);
root.left = mergeTrees(t1.left, t2.left);
root.right = mergeTrees(t1.right, t2.right);
}
return root;
}
The reason for this is that var associates the the closest function as scope and the blocks in the conditional doesn't introduce a new scope. ES6 has fixed this with let and const which works the same as other algol languages though and it's better style to use them.
Related
Is it possible to use loop inside query?
Future<void> addServiceConfig(String uid, List<ServiceConfigModel> model) {
_db.collection('users').document(uid).updateData({
'businessDetails':{
'serviceConfig':FieldValue.arrayUnion([
{
for(int i = 0;i <model.length;i++){
if (model[i].inShop != null) 'inShop': model[i].inShop,
if (model[i].inShopAndClientLocation != null)
'inShopAndClientLocation': model[i].inShopAndClientLocation,
if (model[i].clientLocation != null)
'clientLocation': model[i].clientLocation,
'serviceLocations': model[i].serviceLocations,
'subCategoryId': model[i].subCategoryId
}
}
])
}
});
}
I got this error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Invalid argument: Instance of '_CompactLinkedHashSet>'
You can't use a loop (or many other statements) inside an expression, like the value of a field. One solution is to pull construct the value outside of the update() all and then pass it in:
//var config = new Map()
var result = new List();
for(int i = 0;i < model.length; i++){
var config = new Map();
if (model[i].inShop != null) config['inShop'] = model[i].inShop;
if (model[i].inShopAndClientLocation != null)
config['inShopAndClientLocation'] = model[i].inShopAndClientLocation;
if (model[i].clientLocation != null)
config['clientLocation'] = model[i].clientLocation;
config['serviceLocations'] = model[i].serviceLocations,
config['subCategoryId'] = model[i].subCategoryId;
result.add(config);
}
_db.collection('users').document(uid).updateData({
'businessDetails':{
'serviceConfig': FieldValue.arrayUnion(result)
}
});
I have a program that searches an observable list and displays all of the matching cases on the table. The search works fine, but I am only able to run this part of the program once. The search button stops responding after the program has returned to displaying the full observable list.
I have a separate class(Search.class) that handles all of the logic for searching the observable list.
The code for the search button and text field are below:
partSearchBtn.setOnAction(searchPartEvent ->{
ObservableList<Part> searchPartDisplay = FXCollections.observableArrayList();
String searchQuery = partSearchField.getText();
try{
searchPartDisplay = Search.searchPartByNumber(Integer.parseInt(searchQuery));
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
} catch(NumberFormatException hasText){
searchPartDisplay = Search.searchPartByText(searchQuery);
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
}
});
What changes would I need to make to re-run the search process?
Or should I turn this into a method as part of my Search class that I can reuse?
The search logic is below:
package inventorymngmnt;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Search {
public static ObservableList<Part> searchPartByNumber(int inNum){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchBin.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).contains(e.getName()))){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchPartByText(String inString){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchBin.add(e);
}
}
if(inString.equals(e.getName())){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchProdByNumber(int inNum){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchProd.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).equals(e.getName()))){
searchProd.add(e);
}
}
return searchProd;
}
public static ObservableList<Part> searchProdByText(String inString){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchProd.add(e);
}
}
if(inString.equals(e.getName())){
searchProd.add(e);
}
}
return searchProd;
}
}
It doesn't work, because when you clear the search, the action on the button is still set to clear the search...
Consider a different strategy entirely. You can use a FilteredList as the list for the table. Then just toggle the predicate on the list:
Predicate<Part> noFilter = part -> true;
FilteredList<Part> filteredParts = new FilteredList<>(Inventory.partBin, noFilter);
partTable.setItems(filteredParts);
partSearchBtn.setOnAction(searchPartEvent -> {
if (filteredParts.getPredicate()==noFilter) {
String searchQuery = partSearchField.getText();
try {
int searchNumber = Integer.parseInt(searchQuery);
filteredParts.setPredicate(part -> Search.filterByNumber(part, searchNumber));
} catch (NumberFormatException exc) {
filteredParts.setPredicate(part -> Search.filterByText(part, searchQuery));
}
} else {
filteredParts.setPredicate(noFilter);
}
});
partSearchButton.textProperty().bind(Bindings
.when(filteredParts.predicateProperty().isEqualTo(noFilter))
.then("Search")
.otherwise("Clear"));
and
public class Search {
public static boolean filterByNumber(Part part, int number) {
if (part.getClass() == Inhouse.class) {
Inhouse testIn = (Inhouse) part ;
if (testIn.getMachineID() == number) {
return true ;
}
}
if((number == part.getPartID()) || (number == part.getInstock()) || (number == part.getMax())
|| ( number == part.getMin()) || ((double) number == part.getPrice())
|| (Integer.toString(number).contains(part.getName()))){
return true ;
}
return false ;
}
public static boolean filterByText(Part part, String text) {
//similarly...
}
}
i am trying to implement a log system to the entitiy framework context.
i want to get the deleted element primary key when its state is deleted.
this is my code:
if (item.State == EntityState.Added || item.State == EntityState.Deleted) {
log = new dt_islemLog();
log.eskiDeger = null;
log.islem = (item.State == EntityState.Added) ? Enums.GetDBValue(Enums.islemDurum.EKLENDI) : Enums.GetDBValue(Enums.islemDurum.SILINDI);
log.islemYapanKullanici_id = kullaniciID;
log.nesneAd = item.Entity.GetType().Name;
log.oturum_id = oturumID;
log.zaman = DateTime.Now;
base.SaveChanges();
var ID = GetPrimaryKeyValue(item);
log.nesneID = ID != null ? ID.ToString() : null;
this.dt_islemLog.Add(log);
}
And this is the method that i get the primary key
object GetPrimaryKeyValue(DbEntityEntry entry) {
try {
if (entry.State == EntityState.Detached)
((IObjectContextAdapter)this).ObjectContext.Attach((System.Data.Entity.Core.Objects.DataClasses.IEntityWithKey)entry.Entity);
var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
return objectStateEntry.EntityKey.EntityKeyValues[0].Value;
}
catch(Exception ex) {
return null;
}
}
But i can't attach the (entry.Entitiy) to context because the cast operation is invalid. How can i get the primary key ?
If someone needs i have found the solution. i have updated the primary key method to like this
object GetPrimaryKeyValue(DbEntityEntry entry)
{
try
{
if (entry.State == EntityState.Detached)
this.Set(entry.Entity.GetType()).Attach(entry.Entity);
var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
return objectStateEntry.EntityKey.EntityKeyValues[0].Value;
}
catch
{
return null;
}
}
public void onClick(View v) {
String uname=tv1.getText().toString();
String pass=tv2.getText().toString();
//String copmare=uname.concat(pass);
Cursor cur = db.query("accountTable", // Where are we looking?
new String[]{ "colProject" }, // What do we want back?
"colName = ? AND colPass = ?", // What are we matching?
new String[]{ uname, pass }, // What to put in the "holes"?
null, null, null); // Everything else default...
if (cur != null) {
cur.moveToNext();
}
return;
Intent i = new Intent(FirstAssignmentActivity.this,success.class);
i.putExtra("v1", cur.getString(0));
startActivity(i);
}
Why do I have unreachable code?
You write return ;, so control will exit the function at that point and not reach the final 3 lines of the function (Intent i, etc)
You are returning from the method. None of the code after that will execute.
if (cur != null) {
cur.moveToNext();
}
return; // AFTER THIS NOTHING WILL EXECUTE
I have some data that gets pulled out of a database and mapped to an arraycollection. This data has a field called parentid, and I would like to map the data into a new arraycollection with hierarchical information to then feed to an advanced data grid.
I think I'm basically trying to take the parent object, add a new property/field/variable of type ArrayCollection called children and then remove the child object from the original list and clone it into the children array? Any help would be greatly appreciated, and I apologize ahead of time for this code:
private function PutChildrenWithParents(accountData : ArrayCollection) : ArrayCollection{
var pos_inner:int = 0;
var pos_outer:int = 0;
while(pos_outer < accountData.length){
if (accountData[pos_outer].ParentId != null){
pos_inner = 0;
while(pos_inner < accountData.length){
if (accountData[pos_inner].Id == accountData[pos_outer].ParentId){
accountData.addItemAt(
accountData[pos_inner] + {children:new ArrayCollection(accountData[pos_outer])},
pos_inner
);
accountData.removeItemAt(pos_outer);
accountData.removeItemAt(pos_inner+1);
}
pos_inner++;
}
}
pos_outer++;
}
return accountData;
}
I had a similar problem with a hierarchical task set which was slightly different as it has many root elements, this is what i did, seems good to me:
public static function convertFlatTasks(tasks:Array):Array
{
var rootItems:Array = [];
var task:TaskData;
// hashify tasks on id and clear all pre existing children
var taskIdHash:Array = [];
for each (task in tasks){
taskIdHash[task.id] = task;
task.children = [];
task.originalChildren = [];
}
// loop through all tasks and push items into their parent
for each (task in tasks){
var parent:TaskData = taskIdHash[task.parentId];
// if no parent then root element, i.e push into the return Array
if (parent == null){
rootItems.push(task);
}
// if has parent push into children and originalChildren
else {
parent.children.push(task);
parent.originalChildren.push(task);
}
}
return rootItems;
}
Try this:
AccountData:
public class AccountData
{
public var Id:int;
public var ParentId:int;
public var children:/*AccountData*/Array;
public function AccountData(id:int, parentId:int)
{
children = [];
this.Id = id;
this.ParentId = parentId;
}
}
Code:
private function PutChildrenWithParents(accountData:ArrayCollection):AccountData
{
// dummy data for testing
//var arr:/*AccountData*/Array = [new AccountData(2, 1),
// new AccountData(1, 0), // root
// new AccountData(4, 2),
// new AccountData(3, 1)
// ];
var arr:/*AccountData*/Array = accountData.source;
var dict:Object = { };
var i:int;
// generate a lookup dictionary
for (i = 0; i < arr.length; i++)
{
dict[arr[i].Id] = arr[i];
}
// root element
dict[0] = new AccountData(0, 0);
// generate the tree
for (i = 0; i < arr.length; i++)
{
dict[arr[i].ParentId].children.push(arr[i]);
}
return dict[0];
}
dict[0] holds now your root element.
Maybe it's doesn't have the best possible performance but it does what you want.
PS: This code supposes that there are no invalid ParentId's.
Here's what I ended up doing, apparently you can dynamically add new properties to an object with
object['new_prop'] = whatever
From there, I used a recursive function to iterate through any children so you could have n levels of the hierarchy and if it found anything it would pass up through the chain by reference until the original function found it and acted on it.
private function PutChildrenWithParents(accountData : ArrayCollection) : ArrayCollection{
var pos_inner:int = 0;
var pos_outer:int = 0;
var result:Object = new Object();
while(pos_outer < accountData.length){
if (accountData[pos_outer].ParentId != null){
pos_inner = 0;
while(pos_inner < accountData.length){
result = CheckForParent(accountData[pos_inner],
accountData[pos_outer].ParentId);
if ( result != null ){
if(result.hasOwnProperty('children') == false){
result['children'] = new ArrayCollection();
}
result.children.addItem(accountData[pos_outer]);
accountData.removeItemAt(pos_outer);
pos_inner--;
}
pos_inner++;
}
}
pos_outer++;
}
return accountData;
}
private function CheckForParent(suspectedParent:Object, parentId:String) : Object{
var parentObj:Object;
var counter:int = 0;
if ( suspectedParent.hasOwnProperty('children') == true ){
while (counter < suspectedParent.children.length){
parentObj = CheckForParent(suspectedParent.children[counter], parentId);
if (parentObj != null){
return parentObj;
}
counter++;
}
}
if ( suspectedParent.Id == parentId ){
return suspectedParent;
}
return null;
}