I'm trying to remove an element from an array. I am running into an issue where when I run my program and remove a certain index. I get nulls in the place where the element/index should be removed entirely.
My output is when I execute list.display() in the main method is
Tom, Bob, Richard
However after I execute list.remove() and run the program. I get
null, null, Richard.
Any tips?
public class MyArrayList implements MyList {
private Object[] theList;
public MyArrayList()
{
theList = new Object[0];
}
public boolean add(Object toAdd){
if(toAdd != null) {
Object[] temp = new Object[theList.length + 1];
for(int i = 0; i < theList.length; i++) {
temp[i] = theList[i];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
return false;
}
}
public Object remove(int index) {
if (index >= 0 && index < theList.length) {
Object[] temp = new Object[theList.length - 1];
theList[index] = null;
int j = 0;
for (int i = 0; i < theList.length; i++) {
if (i == index) {
continue;
}
temp[j++] = theList[i];
theList = temp;
}
return temp;
}
return null;
}
public class Main {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("Tom");
list.add("Bob");
list.add("Richard");
list.display();
list.remove(0);
list.remove(1);
list.display();
}
}
Where you call list.remove(0), you should be assigning the result back to list again. For example:
list = list.remove(0);
A couple of other things:
It's generally a bad idea to change the index variable within a loop. It's legal, but leads to logic errors that can be difficult to reason about and diagnose.
You're getting the null in your output because the remove method also mutates the theList when you execute:
theList[index] = null;
Since you're returning a copy of theList you don't need to also set that element of the theList array to null.
Since your code implements MyList which is not available in code, i could not run below sample on your code but you can have below logic in your code. You don't need extra temp array in remove method. Since it an array, you can start traversing array from index which has to be removed and start moving next element by one step before.
public Object remove(int index) {
if (theList == null || index < 0 || index >= theList.length) {
return theList;
}
for (int i = index; i < theList.length; i++) {
theList[i] = theList[i + 1];
}
return null;
}
You can trim array tail if it has more empty places based on some threshold.
the code is doing exactly what you asked it to do. Those removed values are null because you have this line
theList[index] = null;
Also think about what your intentions are.
list.remove(0); <- this will remove the first element so now list would be Rob, Richard
list.remove(1); <- this will remove the 2nd element of the modified list (Rob, Richard) so result would be Rob. This is probably not what you want.
instead of this
if (i == index) {
i++; // risk of out of bounds exception
}
you probably want this instead
if (i == index) {
continue;
}
Related
Got an assignment question which asks to return the first item from an array and then remove it. If the array is empty I should return null. Here is my code:
public String pop(){
if(arrayLength == 0){
return null;
}else{
String[] temp = new String[100];
String firstItem = StringStack[0];
for(int i = 1; i<StringStack.length; i++){
temp[i] = StringStack[i];
}
StringStack = temp;
return firstItem;
}
}
The arrayLength variable is set by this method and works fine:
public int getLength(){
int count = 0;
for (String s : StringStack) {
if (s != null) {
count++;
}
}
return count;
}
I cant figure out what it is I am doing wrong here. Another part of this question is I cant use any collections or Systems.arraycopy so I have to use for loops and other basic operators to solve this. It also has to be an array so I cant use array lists or other data structures.
here is version with two fixed problems:
public String pop() {
if(StringStack == null || StringStack.length == 0)
return null;
String firstItem = StringStack[0];
String[] temp = new String[StringStack.length-1]; // allocate proper size
for(int i = 1; i<StringStack.length; i++){
temp[i-1] = StringStack[i]; // i-1 for temp array
}
StringStack = temp;
return firstItem;
}
Im using an array to hold property details stored alphabetically. I know I can't delete any from the array but i want to know how to find a specified property and then move all the other ones down an index and to replace the last one with null so that I don't have a duplicate at the end. My code never seems to come out of the loop.
public void removeProperty(String reference) {
int index;
Boolean found = false;
for (index = 0; index < this.propertyList.length; index++) {
if (this.propertyList[index].getReference().equalsIgnoreCase(reference)) {
this.propertyList[index] = this.propertyList[index + 1];
found = true;
} else {
index++;
}
if (found = true){
while (index < this.propertyList.length) {
this.propertyList[index] = this.propertyList[index + 1];
}
this.propertyList[this.propertyListSize - 1] = null;
this.propertyListSize--;
}
}
}
Here is a solution that makes no use of boolean flag. Other bugs that are resolved include:
1) increase of index inside for loop
2) while loop goes until last item. this will cause ArrayIndexOutOfBounds exceptuion. the loop should go until item before last.
public void removeProperty(String reference) {
int index;
// loop until reference found or end of array
for (index = 0;
index < this.propertyList.length &&
this.propertyList[index].getReference().equalsIgnoreCase(reference) == false;
index++);
// if we didnt reach end of array - then we found refernce
if (index < this.propertyList.length) {
// loop until item before last
while (index < this.propertyList.length-1) {
this.propertyList[index] = this.propertyList[index + 1];
index++;
}
// nullify last item
this.propertyList[this.propertyList.length-1] = null;
this.propertyListSize--;
}
}
I know this doesn't answer most of your question but you can use apache commons ArrayUtils to remove an item from the array. Here's the link.
public class MyArrayList<T> implements MyList<T>{
int num; //number of things in the list
T[] vals; //to store the contents
#SuppressWarnings("unchecked")
public MyArrayList() {
num = 0;
vals = (T[]) new Object[3];
}
public int size() { //returns number of things in the bag
return num;
}
public T get(int index) { //returns the indexth values
if((index < 0) || (index >= num))
throw new IndexOutOfBoundsException();
return vals[index];
}
#SuppressWarnings("unchecked")
public void add(T s) { //adds s to the list
if(num == vals.length) { //if array is full, make it bigger
T[] temp = (T[]) new Object[vals.length*2];
for(int i=0; i < num; i++)
temp[i] = vals[i];
vals = temp;
}
vals[num] = s;
num++;
}
public boolean contains(T s) { //returns whether s is list
for(int i=0; i < num; i++) { //ending condition should be num
if(vals[i].equals(s)) {
return true;
}
}
return false;
}
public T getUnique(){
T distinct = null;
int count = 0;
for (int i=0; i<vals.length; i++){
distinct = vals[i];
for (int j = 0; j<vals.length; j++){
if (vals[j] == vals[i]){
count++;
}
if (count == 1){
return distinct;
}
}
}
if (distinct == null){
throw new IllegalArgumentException();
}
return distinct;
}
public void addBefore(T input, T before){
for (int i = 0; i<vals.length; i++){
T temp = vals[i];
if(temp.equals(before)){
vals[i-1] = input;
}
}
}
public void removeLast(T s){
for (int i = vals.length; i>=0;i--){
if (vals[i].equals(s)){
vals[i] = vals[i+1];
}
}
}
}
I am working on the ArrayList implementation in Java. I have not been able to finish getUnique, removeLast and addBefore method. I can't seem to be working well with the arrays because I seem to have been replacing the values instead of adding it. A little help on what I am doing wrong.
In addBefore method you are rewritting content on index i-1 with your new varible, you are not adding it. You have to move the rest of the list one index to the right. Also try add new input before first element, it should crash.
In removeLast you are moving second to last variable to the last index (second to last = last). You should be just calling remove on last index.
I assume you want to return unique element in getUnique method. You are almost there, just look at the second for cycle. And btw you dont need help variable to save vals[i], you can just return vals[i].
I need to make my own data structures and part of this is doing an ArrayList. I need to make sure I can add an object at element n while pushing all the others down. Here is my code. Right now it is adding the element twice. It is the function public ReturnObject add(int index, Object item). I need this function to add the object at the specified index and then shift the others down.
public class ArrayList implements List{
public static final int CAPACITY=16;
private int size = 0;
private Object[] data;
ReturnObjectImpl ro;
//constructors
public ArrayList() {
data = new Object[CAPACITY];
} //CONSTRUCTS LIST WITH DEFAULT CAPACITY
public ArrayList(int capacity) { // constructs list with given capacity
data = new Object[capacity];
System.out.println("Created an ArrayList of capacity " + capacity);
}
public boolean isEmpty(){
if(size == 0) {
// System.out.println("The list is empty");
return true;
}
return false;
}
public int size(){
System.out.println("The ArrayList is not full, but currently has " + size + " indexs");
return size;
}
public ReturnObject get(int index){
ro = new ReturnObjectImpl(data[index]);
return ro;
}
public ReturnObject remove(int index){
return null;
}
public ReturnObject add(int index, Object item){
if(index <= size && index < data.length){
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
data[index] = item;
ro = new ReturnObjectImpl(data[index]);
size++;
}
System.out.println("Added to array at " + index);
}
return ro;
}
public ReturnObject add(Object item){
if (data[0] == null){
data[0] = item;
}
//int adding = size + 1;
data[size] = item;
System.out.println("Added item to index " + size);
size++;
return null;
}
//added - but DELETE BEFORE SUBMITTING
public void printAll(){
for(int x = 0; x < data.length; x++){
System.out.println(data[x]);
}
}
}
Obviously, when inserting an object into that array:
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
data[index] = item;
that should not happen within a loop! Insertion should happen exactly once, at the correct index! So even when you keep that loop to move the other elements, that last assignment should go after that "moving loop" is over.
So the point is: you should step back and carefully look what this loop is doing with its loop variable.
In other words: either take a piece of paper and "run" the code yourself; or run it in a debugger.
As this is probably some kind of homework activity, I will leave it with that; it should be really enough to get you going and help you fix your code.
In addition to GhostCat's answer, instead of a for loop, you can just use System.arrayCopy() to 'move' the right part to the right. You only need to know whether your internal array (data) is already full or not. If it is, then you must expand the internal array.
System.arraycopy(this.data, insertIndex, this.data, insertIndex + 1, 1);
Some notes:
The code
if (data[0] == null) {
data[0] = item;
}
will throw an ArrayIndexOutOfBoundsException if ArrayList(0) was called.
The code
if (size == 0) {
// System.out.println("The list is empty");
return true;
}
return false;
can be rewritten to
return (size == 0);
You seem to omit more checks, like the check whether the internal array is full or not. Your current code does not expand the internal array, so if one ever adds more objects than the initial capacity (default 16), then an ArrayIndexOutOfBoundsException is thrown.
I am trying to create a method that sets every instance of the variable elt in an array to null, and then shift every variable after it to the left. The current code that I have written only sets the first instance of the variable to null and shifts all other variable to the left, but does not set any other instance of elt to null. The code I have so far is below.
public T remove(T elt) {
boolean exist = false;
for (int i=0; i<data.length; i++) {
if (data[i] == elt) {
data[i] = null;
size--;
exist = true;
for (++i; i < data.length; i++) {
data[i-1] = data[i];
}
}
}
if (exist == true)
return elt;
else
return null;
}
In main, I have the following code:
public static void main(String[] args) {
Bag<String> sbag = new Bag<String>();
sbag.add("Noriko");
sbag.add("hello");
sbag.add("Buddy");
sbag.add("Mary");
sbag.add("Peter");
sbag.add("hello");
sbag.remove("hello");
When I print the array, I expect the following output:
Noriko
Buddy
Mary
Peter
Instead I get:
Noriko
Buddy
Mary
Peter
hello
This tells me it is only setting the first instance of elt to null, moving every variable to the left, and stopping. Can anyone tell me how I can fix my code so that it sets every instance of the variable elt null?
The common technique to the "remove all and shift" problem is to do it all in one loop with two separate indexes - one for reading, and one for writing:
int rd = 0, wr = 0;
while (rd != data.length) {
if (data[rd] != elt) { // Shouldn't you use equals() instead?
data[wr++] = data[rd++];
} else {
rd++;
}
}
while (wr != data.length) {
data[wr++] = null;
}
This technique is very useful in practice. I highly recommend working through an example or two with paper and pencil to make sure that you fully understand it.
Both your innner and outer loop use the variable i. When the first match is found, the record is removed and i is incremented to data.length (when shifting the remaining records to the left). When you get back to the outer loop, i = data.length and the outer loop terminates.
You should use a different variable for your inner loop.
From the looks of your code it would seem like you would want to use a "List" type.
With this you can then add and remove variables without having to write an entire new function to do it.
For the sake of excercise:
public T remove(T elt) {
boolean exist = false;
for (int i=0; i<size; i++) { // changed data.length to size to avoid unnecessary iterations over deleted positions
while (data[i] == elt) { // changed if to while
data[i] = null;
size--;
exist = true;
for (int j = i+1; j < data.length; j++) { // changed iteration variable, we don't want to move i
data[j-1] = data[j];
}
}
}
if (exist == true)
return elt;
else
return null;
}