The code has migrated from Java to C #.
Java code :
for (List<ItemNY> level : highU.getLevels())
{
Iterator<ItemNY> iterItemset = level.iterator();
while(iterItemset.hasNext())
{
ItemNY c = iterItemset.next();
// Code...
if(c.getU() < min)
{
iterItemset.remove();
highU.decreaseCount();
}
}
}
C# code : (Code written after convert)
foreach (List<ItemNY> level in highU.getLevels())
{
ItemNY c;
using (IEnumerator<ItemNY> iterItemset = level.GetEnumerator())
{
while (iterItemset.MoveNext())
{
c= iterItemset.Current;
//CODE
foreach (TransactionTP transaction in database.getTransactions())
{
int transactionUtility = 0;
int matchesCount = 0;
for (int i = 0; i < transaction.size(); i++)
{
if (c.getItems().Contains(transaction.get(i).item))
{
transactionUtility += transaction.getItemsUtilities()[i].utility;
matchesCount++;
}
}
if (matchesCount == c.size())
{
c.incrementUtility(transactionUtility);
}
}
//END CODE
if (c.getU() < min)
{
iterItemset.remove(); //ERROR
highU.decreaseCount();
}
}
}
}
I want to remove an item from IEnumerator, how can I do this?
Note : The code written in the C # section is more complete, More code is written in the (CODE) to (END CODE) section.
I want to remove an item from IEnumerator, how can I do this?
Easy: you don't.
I do not know Java, but that idea does not make sense in .NET. As you can read in the documentation:
Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.
As it is also mentioned, foreach should be used instead of IEnumerator<T> directly:
foreach (List<ItemNY> level in highU.getLevels())
{
foreach (var item in level)
{
if (item.getU() < min)
{
level.Remove(item); //Error, you are modifying a collection being enumerated
highU.decreaseCount();
}
}
}
You would have to put the elements that match the filter in a new collection so you could remove them from level.
foreach (List<ItemNY> level in highU.getLevels())
{
var filteredItems = new List<ItemNY>();
foreach (var c in level)
{
foreach (TransactionTP transaction in database.getTransactions())
{
int transactionUtility = 0;
int matchesCount = 0;
for (int i = 0; i < transaction.size(); i++)
{
if (c.getItems().Contains(transaction.get(i).item))
{
transactionUtility += transaction.getItemsUtilities()[i].utility;
matchesCount++;
}
}
if (matchesCount == c.size())
{
c.incrementUtility(transactionUtility);
}
}
if (c.getU() < min)
{
filteredItems.Add(c);
highU.decreaseCount();
}
}
foreach (var item in filteredItems)
{
level.Remove(item);
}
}
If the true goal is to remove items from the list then I would use List.RemoveAll, with conditions defining which to remove.
If you need the extra counter update then you take a size before and after. Though at least in the presented case there is no need for the decreaseCount method, as it appears to track size of the list, so I would drop the method, and rely on the list Count.
Related
I've been trying to set up a translator by using a binary tree to set up the morsecode's structure.
I consistently receive a stack overflow error when re-executing the method
private String decode(String pCode, BinaryTree<String> pTree)
{
int loop1 = 0;
int loop2 = 0;
BinaryTree<String> tree = morsetree;
if (!pCode.isEmpty())
{
if (loop2 <= pCode.length())
{
while (pCode.substring(loop, loop+1) == " ")
{
loop2++;
}
}
if (loop2 > 5)
{
return null;
}
for (int i=0;i<loop2;i++)
{
if (pCode.substring(i, i+1) == "-")
{
tree = tree.getRightTree();
}
else
{
tree = tree.getLeftTree();
}
}
System.out.println(tree.getContent());
return getLetter(pCode.substring(loop2, pCode.length())
,morsetree);
}
return null;
}
Havent read the whole code but this part alone seems problematic.
while (pCode.substring(loop, loop+1) == " ")
{
loop2++;
}
Where was “loop” defined? How do you assure that the while loop ends? It seems like the condition wouldnt produce a different result after loop runs
I have a problem... it's basically that my code is ugly and I don't like it. I was wondering if there was a way to simplify it (I use java 8)
I have these "code blocks" that follow this pattern, I have about 5 or 6 of them within a method so this method looks very repetitive and ugly.
The loops are all the same, just the code varies inside.
Is there any way to simplify this?
CODE BLOCK EXAMPLE
String id = null;
for (int i=0; i< NUM_CHECKS; i++) {
// BEGIN VARIABLE CODE
id = getPrice();
if (id != null) break;
// END VARIABLE CODE
// sleep between checks
if (i < NUM_CHECKS -1) Thread.sleep(DELAY);
}
EXAMPLE
String id = null;
for (int i=0; i< NUM_CHECKS; i++) {
// BEGIN VARIABLE CODE
id = getPrice();
if (id != null) break;
// END VARIABLE CODE
// sleep between checks
if (i < NUM_CHECKS -1) Thread.sleep(DELAY);
}
for (int i=0; i< NUM_CHECKS; i++) {
// BEGIN VARIABLE CODE
x=x*2;
if (x>25) break;
// END VARIABLE CODE
// sleep between checks
if (i < NUM_CHECKS -1) Thread.sleep(DELAY);
} etc... a couple more blocks
How about coding an abstraction to contain all the boilerplate?
class MyLoop
{
private int numChecks;
private int delay;
public MyLoop(int numChecks, int delay) {...}
public void loopAndSleep(MyTask task)
throws InterruptedException
{
// Update: It is important to set properly the order of the looping conditions,
// to stop invoking hasEnded() as soon as i<numChecks==false (Thaks to Simon Eismann).
for (int i=0; i<numChecks && !task.hasEnded(); i++)
{
if (i < numChecks -1)
{
Thread.sleep(DELAY);
}
}
}
}
interface MyTask
{
public boolean hasEnded();
}
So, you can replace each one of your 5-6 places in your program by:
new MyLoop(NUM_CHECKS, DELAY).loopAndSleep(new MyTask(){...});
By properly extending MyTask you can give them specific status variables.
If you want to try some operation until the return value is available, you may do the following (Java-8 way):
public static <T> Optional<T> retryWithDelay(int numberOfChecks, int delay,
Supplier<Optional<T>> supplier) throws InterruptedException {
for(int i=0; i<numberOfChecks; i++) {
if(i > 0)
Thread.sleep(DELAY);
Optional<T> result = supplier.get();
if(result.isPresent()) return result;
}
}
And use it like this:
String id = retryWithDelay(NUM_CHECKS, DELAY, () -> Optional.ofNullable(getPrice()))
.orElse(null);
Or if you don't like optionals for some reason, you can stick with null:
public static <T> T retryWithDelay(int numberOfChecks, int delay,
Supplier<T> supplier) throws InterruptedException {
for (int i = 0; i < numberOfChecks; i++) {
if (i > 0)
Thread.sleep(delay);
T result = supplier.get();
if (result != null)
return result;
}
return null;
}
And use it like this:
String id = retryWithDelay(NUM_CHECKS, DELAY, () -> getPrice());
Or using method reference:
String id = retryWithDelay(NUM_CHECKS, DELAY, this::getPrice);
Note that the second example with x = 2*x is more difficult as it has some mutable state. It can be solved in dirty way like this:
AtomicInteger x = new AtomicInteger(1);
Integer result = retryWithDelay(NUM_CHECKS, DELAY, () -> {
int val = x.get()*2;
x.set(val);
return val > 25 ? val : null;
});
However I hope this version was just for illustration, not the real code.
There's also somewhat more sophisticated approach which probably abuses the API, but allows more flexibility. You can create an IntStream of increasing numbers, but they are available with given delay:
public static IntStream delayedStream(int numberOfChecks, int delay) {
return IntStream.range(0, numberOfChecks)
.peek(x -> {
if(x > 0) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// ignore
}
}
});
}
So the first problem can be solved now as:
String id = delayedStream(NUM_CHECKS, DELAY)
.mapToObj(x -> getPrice())
.filter(Objects::nonNull)
.findFirst().orElse(null);
And the second can be solved like this (assuming initial x value is 1):
int x = delayedStream(NUM_CHECKS, DELAY)
.map(idx -> 1 << (idx+1))
.filter(val -> val > 25)
.findFirst().orElse(-1);
The structure you provide is called a "polling loop" and you are correct, it is poor programming style, as are all the replies that contain the same polling loop.
It would be far better to use events.
Look in the "getPrice()" function, get to wherever that return value is being changed, and create an event when the change happens. Then in your code write a handler and in the handler do all the stuff that currently happens after your polling loop succeeds.
You can use recursion to make to loop reusable, but this would only make sense if you use the loop a lot.
public void loopWithDelay(int numberOfChecks, int delay, Runnable r) {
if (numberOfChecks != 0) {
r.run();
loopWithDelay(numberOfChecks - 1, delay, r);
Thread.sleep(DELAY);
}
}
The actual call would look something like this:
loopWithDelay(5, 1000, new Runnable() {
#Override
public void run() {
//Variable code goes here
}
});
On a general note, are you sure you want to wait DELAY seconds after an action or have the action occur every DELAY seconds?
EDIT:
I am dumb, no need for recursion, this works aswell:
public void loopWithDelay(int numberOfChecks, int delay, Runnable r) {
for (int i = 0; i < numberOfChecks; i++) {
r.run();
if (i != numberOfChecks -1)
Thread.sleep(DELAY);
}
}
I can't figure out why I get the error:
java.util.NoSuchElementException null(in java.util.Scanner)
in my method:
public void processTransactions(Scanner transFile){
while (transFile.hasNext()){
for(i = 0; i < ids.length; i++){
finalInventory[i] = startingInventory[i];
if(ids[i] == transFile.next()){
finalInventory[i] += transFile.nextInt();
}
}
}
}
this is my construtor:
public SoftDrinkInventory(Scanner inventoryFile) {
initializeString(names);
initializeString(ids);
initializeInt(startingInventory);
initializeInt(finalInventory);
initializeInt(transactionCounts);
while (inventoryFile.hasNext()){
names[i] = inventoryFile.next();
ids[i] = inventoryFile.next();
startingInventory[i] = inventoryFile.nextInt();
i++;
}
}
All variables have been declared previously in the class.
I'm guessing a little, but I think your code was supposed to be this.
public void processTransactions(Scanner transFile){
while (transFile.hasNext()){
String key = transFile.next();
int value = transFile.nextInt();
for(i = 0; i < ids.length; i++){
finalInventory[i] = startingInventory[i];
if(ids[i].equals(key)){
finalInventory[i] += value;
}
}
}
}
You only want to do the next() and the nextInt() once per iteration of the while loop. Currently, you are repeating the next() in every iteration of the for loop, which really isn't what you want.
Note that this isn't the most efficient solution to your problem, but it will take away your error.
Also, you haven't specified the type of ids, but I've assumed that it's a String[].
You are calling hasNext() but using nextInt() ... One solution is to use,
while (transFile.hasNextInt()){
// As before.
}
Another is to skip anything that isn't an int, perhaps like so
while (transFile.hasNext()){
if (!transFile.hasNextInt()) {
transFile.next();
continue;
}
// As before.
}
My code is below. It is a sorting method included in a project instead of bubblesort for efficiency of code. My problem is that I keep getting errors which are:
array required, but java.util.List<Inpatient> found
&
QuickSort(java.util.List<Inpatient>,int,int) in UtilitiesInpatient cannot be applied to (int,int)
I've tried doing some research but a lot of algorithms vary a lot depending on string or integer sorting and also, research on the errors themselves were highly unhelpful. Many thanks for any help or tips!
public void QuickSort (List<Inpatient> inpatientArrayListIn, int first, int last)
{
// Quick Sort
List<Inpatient> pivotValue = new ArrayList<Inpatient>();
List<Inpatient> lowerPointerValue = new ArrayList<Inpatient>();
List<Inpatient> upperPointerValue = new ArrayList<Inpatient>();
int pivotIndex = first;
Inpatient tempPatient = (inpatientArrayListIn.get(pivotIndex));
String pivot = tempPatient.getSurname();
int upperPointer = first;
int lowerPointer = last;
while (upperPointer < lowerPointer) {
while ((inpatientArrayListIn.get(upperPointer).getSurname().compareToIgnoreCase(pivot) <= 0) && (upperPointer < last)) {
upperPointer++;
}
while (((inpatientArrayListIn.get(lowerPointer).getSurname()).compareToIgnoreCase(pivot) > 0) && (lowerPointer > first)){
lowerPointer--;
}
if (upperPointer < lowerPointer) {
for (int i = 0; i <= inpatientArrayListIn.size(); i++) {
upperPointerValue[i] = ((inpatientArrayListIn.get(upperPointer)));
lowerPointerValue[i] = ((inpatientArrayListIn.get(lowerPointer)));
}
/* defaultTable.removeRow (upperPointer);
defaultTable.insertRow (upperPointer, lowerPointerValue);
defaultTable.removeRow (lowerPointer);
defaultTable.insertRow (lowerPointer, upperPointerValue);
*/
++upperPointer;
--lowerPointer;
}
}
if ((inpatientArrayListIn.get(lowerPointer).getSurname()).compareTo(pivot) < 0) {
for (int i = 0; i <= inpatientArrayListIn.size(); i++) {
pivotValue[i] = inpatientArrayListIn.get(pivotIndex);
lowerPointerValue[i] = (inpatientArrayListIn.get(lowerPointer));
}
/*
defaultTable.removeRow (pivotIndex);
defaultTable.insertRow (pivotIndex, lowerPointerValue);
defaultTable.removeRow (lowerPointer);
defaultTable.insertRow (lowerPointer, pivotValue);
*/
}
// Value in lowerPointer is now the pivot
if (first < (lowerPointer-1))
{
QuickSort (first, (lowerPointer-1));
}
if ((lowerPointer+1) < last)
{
QuickSort ((lowerPointer+1), last);
}
}
In this portion:
if (first < (lowerPointer-1))
{
QuickSort (first, (lowerPointer-1));
}
if ((lowerPointer+1) < last)
{
QuickSort ((lowerPointer+1), last);
}
You are missing the first argument, List<Inpatient> inpatientArrayListIn, exactly as the error message describes. Also, you are trying to use List as an array, as in:
upperPointerValue[i] = ((inpatientArrayListIn.get(upperPointer)));
If we look at the documentation for List, the method you want is set(int index, E element), so the above would be:
upperPointerValue.set(i, inpatientArrayListIn.get(upperPointer));
There really is not much more one can say about the problems you are facing that the compiler isn't already telling you.
For a school project i have a list of 50k containers that arrive on a boat.
These containers need to be sorted in a list in such a way that the earliest departure DateTimes are at the top and the containers above those above them.
This list then gets used for a crane that picks them up in order.
I started out with 2 Collection.sort() methods:
1st one to get them in the right X>Y>Z order
Collections.sort(containers, new Comparator<ContainerData>()
{
#Override
public int compare(ContainerData contData1, ContainerData contData2)
{
return positionSort(contData1.getLocation(),contData2.getLocation());
}
});
Then another one to reorder the dates while keeping the position in mind:
Collections.sort(containers, new Comparator<ContainerData>()
{
#Override
public int compare(ContainerData contData1, ContainerData contData2)
{
int c = contData1.getLeaveDateTimeFrom().compareTo(contData2.getLeaveDateTimeFrom());
int p = positionSort2(contData1.getLocation(), contData2.getLocation());
if(p != 0)
c = p;
return c;
}
});
But i never got this method to work..
What i got working now is rather quick and dirty and takes a long time to process (50seconds for all 50k):
First a sort on DateTime:
Collections.sort(containers, new Comparator<ContainerData>()
{
#Override
public int compare(ContainerData contData1, ContainerData contData2)
{
return contData1.getLeaveDateTimeFrom().compareTo(contData2.getLeaveDateTimeFrom());
}
});
Then a correction function that bumps top containers up:
containers = stackCorrection(containers);
private static List<ContainerData> stackCorrection(List<ContainerData> sortedContainerList)
{
for(int i = 0; i < sortedContainerList.size(); i++)
{
ContainerData current = sortedContainerList.get(i);
// 5 = Max Stack (0 index)
if(current.getLocation().getZ() < 5)
{ //Loop through possible containers above current
for(int j = 5; j > current.getLocation().getZ(); --j)
{ //Search for container above
for(int k = i + 1; k < sortedContainerList.size(); ++k)
if(sortedContainerList.get(k).getLocation().getX() == current.getLocation().getX())
{
if(sortedContainerList.get(k).getLocation().getY() == current.getLocation().getY())
{
if(sortedContainerList.get(k).getLocation().getZ() == j)
{ //Found -> move container above current
sortedContainerList.add(i, sortedContainerList.remove(k));
k = sortedContainerList.size();
i++;
}
}
}
}
}
}
return sortedContainerList;
}
I would like to implement this in a better/faster way. So any hints are appreciated. :)
I think you probably want to sort with a single Comparator that compares on all of the criteria. E.g.:
compareTo(other)
positionComparison = this.position.compareTo(other.position)
if positionComparison != 0
return positionComparison
return this.departureTime.compareTo(other.departureTime)