Search and remove item from array - java

Does anyone why when the search value matches a value stored in array it doesn't remove that item?
String titles = "";
String lengths = "";
for (int i = 0; i < numOfSongs; i++) {
titles += songTitles[i] + " ";
lengths += songLengths[i] + " ";
}
String search = JOptionPane.showInputDialog("Enter a song title to remove it or -1 to end:");
while (!search.equals("-1")) {
for (int i = 0; i < numOfSongs; i++) {
if (search.equalsIgnoreCase(songTitles[i])) {
songTitles[i] = songTitles[i + 1];
}
}
numOfSongs--;
JOptionPane.showMessageDialog(null, "**Current Playlist**" + "\nSong titles: " + titles + "\nSong lengths: " + lengths);
search = JOptionPane.showInputDialog("Enter a song title to remove it or -1 to end:");
}

Many things are wrong with this code:
You never update titles and lengths inside your while loop, so whatever happens inside has no effect on what's printed in the dialog
When you find song title to remove, you copy the next song title to the current one, but don't copy anything else, so [a, b, c, d] will after removing b change to [a, c, c, d] - you need to shift everything behind the deleted element left by one position
When you find song title to remove, you assume the i+1th position is valid - this isn't true if you remove the last song on the list, that would either fail with ArrayIndexOutOfBounds exception or copy some garbage from behind the currently valid playlist
You're never updating songLengths array
Concatenating strings in a loop using += is very ineffective - use StringBuilder instead

Sorry this took a while, but hopefully it's pretty comprehensive.
I am assuming that song title and song length are supposed to correspond with one another, so that if you remove the title you also remove the length? It may be good to create a class, e.g. Song, which has a field for both title and length. There are more methods you can add, e.g. setters, default constructor, etc. You can also include more fields like Song Artist, year, etc. I'm just including those required for your program to run.
I'll use red's suggestion of an ArrayList, so you can see what they meant (in case you haven't learned what that is)
public class Song {
String title; //these are known as fields, or instance variables
String length;
public Song(String title, String length) {
this.title = title;
this.length = length;
}
public String getTitle() {
return title;
}
public String getLength() {
return length;
}
//you can format this differently. Just keeping it simple though. If you don't include toString() method in this class, you will run into some problems if you try to print the object itself.
public String toString() {
return "title = " + title + " length = " + length + "\n";
}
From here, in your main method you can do...
ArrayList<Song> playlist = new ArrayList<>();
//here, inside a do-while loop, get input for each song, then store into strings, let's call them songTitle and songLength. I'm not showing this step since I don't know where you want the input to come from, but I'm sure you can figure this bit out. ;)
Then we create objects and add them to your list like so:
Song song = new Song(songTitle, songLength); //creates a new object with arguments songTitle and songLength
playlist.add(song); //adds object to array list.
Once you have your playlist set up, we return to your question regarding song removal, and here is where Lists(there are different ones you can use)/Objects really make things far simpler.
Iterator<Song> songIt = playlist.iterator();
while (!search.equals("-1") && songIt.hasNext()) {
if (search.equalsIgnoreCase(songIt.next().getTitle())) {
songIt.remove();
}
}
And printing is simple too.
for (int i = 0; i < playlist.size(); i++) {
System.out.println(playlist.get(i);
}
-EDIT-
To put into perspective, here is what you would have to do for removal in your program using array and without objects.
int removeCount = 0;
while (!search.equals("-1")) {
for (int i = 0; i < songTitles.length; i++) {
if (search.equalsIgnoreCase(songTitles[i])) {
for (int j = i; j < songTitles.length - 1; j++) {
songTitles[j] = songTitles[j + 1];
songLengths[j] = songLengths[j + 1];
removeCount ++;
}
}
}
}
String remainingTitles[] = new String[songTitles.length - removeCount];
String remainingLengths[] = new String[songTitles.length - removeCount];
for (int i = 0; i < temp.length; i++) {
remainingTitles[i] = songTitles[i];
remainingLengths[i] = songLengths[i];
}
Suffice it to say, this is much more ugly, and there's many more places where you can make a stupid mistake that may or may not throw an exception.

Related

The content of an array is suspiciously doubled

I have been building an app that simulates the way a printer works. While designing the app, I have created the method below that splits a String content depending on the number of pages required. All the function seems to process the data correctly but I don't know why the method keeps doubling the content of an array it's supposed to return. Here's the method.
public ArrayList<String> splitContentIntoPages(){
int startPosition = 0;
int endIndexCalc = 0;
for(int i=0; i<getPages(); i++){
if((getContent().length() - endIndexCalc) >= getSize().getCapacity()){
System.out.println("Start " + startPosition);
endIndexCalc = startPosition + (getSize().getCapacity());
this.pagesContent.add(getContent().substring(startPosition, endIndexCalc));
startPosition += getSize().getCapacity();
System.out.println("End " + endIndexCalc);
}else{
this.pagesContent.add(getContent().substring(startPosition));
}
}
System.out.println("Size of the array " + this.pagesContent.size() + " getPages() " + getPages() + "");
for(int i=0; i<this.pagesContent.size(); i++){
System.out.println("The content :" + this.pagesContent.get(i));
}
return this.pagesContent;
}
I need some fresher eye on the issue. I have spent too much time on that trying to understand what's wrong. Thanks a lot guys!
Here's the version without debugs
public ArrayList<String> splitContentIntoPages(){
int startPosition = 0;
int endIndexCalc = 0;
for(int i=0; i<getPages(); i++){
if((getContent().length() - endIndexCalc) >= getSize().getCapacity()){
endIndexCalc = startPosition + (getSize().getCapacity());
this.pagesContent.add(getContent().substring(startPosition, endIndexCalc));
startPosition += getSize().getCapacity();
}else{
this.pagesContent.add(getContent().substring(startPosition));
}
}
return this.pagesContent;
}
this is the test entry extraxt. Basically the method aboe is processing the string of chars
that's the outcome. Basically, the string is supposed to be split into the number of pages - in this case 2. However, the array that is holding the split element of the strings holds 4 pieces of strings instead of two. It's all doubled. And I have no idea why
Either clear this.pagesContent at the beginning of splitContentIntoPages() or create new ArrayList<String> newA = new ArrayList<String>() at the beginning, add everythig to this new arrayList and at the end of splitContentIntoPages() do this.pagesContent = newA

How to print String

I have this String which I want to return but I cannot because it says that "print" cannot be resolved as a variable. This is my code:
public static String enrcyptText(String str, int shift){
int count = 0;
String[] parts = str.split("[\\W]");
for(String word : parts){
shift = shift * (count + 1) + 1;
count++;
encryptWord(word, shift);
String[] phrase = new String[]{word};
String print = String.join(" ", phrase);
}
return print;
}
any Idea?
There are several problems there.
You've declared print only within the loop body. It doesn't exist outside of it. So you need to move your String print outside the loop.
You're also assigning to it on every loop iteration, which will overwrite the previous value it had. It's unclear what you want to do instead, but you're not going to want to do that.
These two lines also don't make any sense:
String[] phrase = new String[]{word};
String print = String.join(" ", phrase);
Since there will only be one entry in phrase, you'll end up with print having the same value word had.
You seem to expect that encryptWord can modify the string passed into it. It can't.
Taking a stab at it, I'm thinking your goal is to "encrypt" individual words from a sentence, then recombine the result into a space-delimited set of encrypted words. If so, see comments:
public static String enrcyptText(String str, int shift){
int count = 0;
String[] parts = str.split("[\\W]");
// For updating the array, better to use the classic
// for loop instead of the enhanced for loop
for (int i = 0; i < parts.length; ++i){
shift = shift * (count + 1) + 1;
count++; // Could do this before previous line and remove the + 1 in (count + 1)
parts[i] = encryptWord(parts[i], shift); // See note below
}
return String.join(" ", parts);
}
Note that I'm using a return value from encryptWord. That's because strings in Java are immutable (cannot be changed), and so encryptWord can't change what we pass into it; it can only give us back a new string to use instead.
print variable has scope inside the braces.You should move the print variable outside braces to make it visible to the code.Also,since it is a local variable ,print should be initialized with a default value(in my case,it is null).The compiler will complain that print remain uninitialized(though this is not related to the main question)
public static String enrcyptText(String str, int shift){
int count = 0;
String[] parts = str.split("[\\W]");
String print = null;
for(String word : parts){
shift = shift * (count + 1) + 1;
count++;
encryptWord(word, shift);
String[] phrase = new String[]{word};
print = String.join(" ", phrase);
}
return print;
}
You have a logic error in your code: you are encrypting correctly each word but you are not building correctly the encrypted phrase. In each iteration of the loop, you are recreating the phrase when you should be adding element to the phrase array.
public static String enrcyptText(String str, int shift) {
int count = 0;
String[] parts = str.split("[\\W]");
String[] phrase = new String[parts.length]; // initialising an array containing each encrypted word
for (String word : parts) {
shift = shift * (count + 1) + 1;
count++;
String encryptedWord = encryptWord(word, shift);
phrase[count - 1] = encryptedWord; // updating the encrypted phrase array
}
return String.join(" ", phrase); // joining the phrase array
}
In this code, we are creating a phrase array before the loop. In each iteration, we update this array with the encryped word. When we have all the encrypted words, the loop terminates and we join all of the parts together.
I am also guessing that the encryptedWord actually returns the encrypted word. This method can't modify the word given as parameter.

Adding to an ArrayList using input from GUI

I first created an arraylist in another part of the program, then used for loops to put it in the text area. Now, I want to take input from the text field, add that to the arraylist, and display the entire array, including the new element added. I tried using a for loop again, but when i click "add" while running, the program just freezes and nothing happens. Any suggestions?
Thanks.
private void btnDisplayActionPerformed(java.awt.event.ActionEvent evt) {
// Using a for loop to display unsorted list, sorting the list, then using a for loop again to display the sorted list
String strUnsortedList = "";
for(int i = 0; i < strCDNames.size(); i++) {
strUnsortedList += strCDNames.get(i) + "\n";
}
Collections.sort(strCDNames);
String strSortedList = "";
for(int i = 0; i < strCDNames.size(); i++) {
strSortedList += strCDNames.get(i) + "\n";
}
txtOutput.setText("Unsorted Order: \n" + strUnsortedList + "\nSorted Order: \n" + strSortedList);
}
private void btnAddActionPerformed(java.awt.event.ActionEvent evt) {
String strAddedList = "";
for (int i = 0; i < strCDNames.size(); i++) {
strAddedList += strCDNames.add(txtInputTitleArtist.getText());
}
txtOutput.setText(" " + strAddedList);
}
for (int i = 0; i < strCDNames.size(); i++) {
strAddedList += strCDNames.add(txtInputTitleArtist.getText());
}
This is an infinite loop. You keep adding to the list, which means that the list size will keep increasing. Hence i will always be lesser than strCDNames.size().
Instead you can do something like this:
strCDNames.add(txtInputTitleArtist.getText());
String strAddedList = String.join(" ", strCDNames);
Vivin is right. I just want to add that the arraylist add method returns a boolean (https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-E-). So, in this case strAddedList wouldn't even be properly updated.

How do I subtract some elements from one array which (element) are already in another array?

I have two different arrays and they both contain the same type of element. The elements are obtained from user input. And the arrays can store fixed size of element.
*Let's say that fisrt one is basically an arrayList and it adds the user input into the list.
The second one is simply an array which also gets value from user input. All the elements of second array are also contained in the first array and the length of this array is less than the first array*
Now I want to print an array which is the result of first array-second array.
This is the program I am working on right now. You may avoid this coding just to give me a theoritical concept for doing that.
package issuetracking;
import java.util.*;
public class IssueTrackingObject {
ArrayList<String> crIss = new ArrayList<String>();
Scanner input = new Scanner(System.in);
boolean crIss_bool;
int numOfSolvedIss;
private String[] solvedIss;
//lets user create some issues and add them into an arrayList
public void createIssue() {
System.out.println("Enter 5 issues: ");
for (int i = 0; i < 5; i++) {
System.out.println("Issue " + (i + 1 + ": "));
crIss_bool = crIss.add(input.nextLine());
}
}
//Let user mark some issues as solved (which are already in the list that the user has just created)
public void solvedIssue() {
System.out.println("How many solved issue you have(Must be less than 5): ");
numOfSolvedIss = input.nextInt();
solvedIss = new String[numOfSolvedIss];
for (int k = 0; k < numOfSolvedIss; k++) {
System.out.print("Enter solved issue(REMEMBER THAT THE SOLVED ISSUE MUST BE FROM ONE OF THEM YOU ALREADY HAVE CREATED)no. " + (k + 1) + ": ");
solvedIss[k] = input.next();
}
}
public void printUnsolvedIssue() {
//print out the elements of createIssue() that doesn't belong to the solvedIssue()
}
You can use a simple solution like this:
for (String solved : solvediss) {
if (solved != null) crIss.remove(solved);
}
This will remove all the Strings from the list that are in the array.
Of course, you could also do this.
crIss.removeAll(Arrays.asList(solvediss));
Go over your second array and use the remove method in arraylist to remove every element of second array from the first.
for (int i = 0; i < solvedIss.length; i++) {
crIss_bool = crIss.remove(solvedIss[i]);
}
Removing the elements might be the simplest method in this case, but it causes original list to change.
If you do not wish to have any destructive modification to the original list, you could perform a simple search like following.
for (String issue : crIss) {
bool isUnSolved = true;
for (String solvedIssue : solvedIss) {
if (issue.equals(solvedIssue)) {
isUnSolved = false;
break;
}
}
if (isUnSolved) {
// Print the 'issue' or do whatever you want to do with it.
}
}
Hope this helps.
Good luck.

Delete Method without Array List

I need to implement a delete method WITHOUT USING AN ARRAY LIST. I need to use a set of loops to do it. Here is my delete method and add method as well as any other important variables used. Any advice on what is wrong with my code would be great.
EDITED: Changed the comparing of references to values. Seems to work repeatedly.
final int MAX_DEVICES = 5;
// Array of devices
private Device list[] = new Device[MAX_DEVICES];
// Number of Devices currently in the list
// "Valid" Devices are stored in cells 0 - (numDevices - 1)
private int numDevices = 0;
Scanner stdin; // read from stdin
private void Add()
{
String thisName;
int numThisRead;
float thisInitVal;
thisName = stdin.next();
numThisRead = stdin.nextInt();
thisInitVal = stdin.nextFloat();
if(numDevices > MAX_DEVICES)
System.out.println("The List was full. " + thisName +
" was not added to the list.");
else
{
Device myDevice = new Device(thisName, numThisRead, thisInitVal);
list[numDevices] = myDevice;
numDevices ++;
System.out.println(thisName + " device has been added to the list.");
}
}
private void Delete() //ASK QUESTION
{
String thisDelete;
thisDelete = stdin.next();
for(int i = 0; i < MAX_DEVICES; ++i)
{
if(list[i].getName().equals(thisDelete)) //if you find the name
{
System.out.println(list[i].getName() + " was deleted from the "
+ "list.");
for(int j = i; j < numDevices - 1; j++)
list[j] = list[j + 1];
numDevices--;
return;
}
}
System.out.println(thisDelete + " not deleted. It is not in the list.");
}
If you need to avoid using data type List, you can place the objects in the array. Then you can declare an array one element smaller than the current array and copy all the elements, except for the one you want deleted, over into the new array. Then return the new array.

Categories

Resources