I have a set in Java looks like
[0.99998945, line10Rule:14013, noOfCommits:0]
and, I want to remove all digital numbers and colon ':' from its element to get
[line10Rule, noOfCommits]
What is the best way to do that?
Now corrected:
String[] array = new String[set.size()]; // create a String array of the same size as the set
set.toArray(array); // copy the sets content into the array
set.clear(); // clear the set
for (String string : array) { // iterate through the array
set.add(string.replaceAll("[0-9]*$", "")); // remove the digits and put the resulting String back into the set
}
#jlordo: thanks for pointing it out. I forgot, that the iterator works on a copy of the String. This may not be elegant (iterating through so many loops etc) but it works :D
regards Christoph
Try this
List<String> list = new ArrayList<String>(Arrays.asList("0.99998945", "line10Rule:14013", "noOfCommits:0"));
ListIterator<String> i = list.listIterator();
while(i.hasNext()) {
String s = i.next();
int p = s.indexOf(':');
if (p > 0) {
i.set(s.substring(0, p));
} else {
i.remove();
}
}
System.out.println(list);
output
[line10Rule, noOfCommits]
No way, you will have to recreate the set item by item. To replace numbers with "", consider String.replace().
Related
I'm trying to count the occurrences per line from a text file containing a large amount of codes (numbers).
Example of text file content:
9045,9107,2376,9017
2387,4405,4499,7120
9107,2376,3559,3488
9045,4405,3559,4499
I want to compare a similar set of numbers that I get from a text field, for example:
9107,4405,2387,4499
The only result I'm looking for, is if it contains more than 2 numbers (per line) from the text file. So in this case it will be true, because:
9045,9107,2376,9017 - false (1)
2387,4405,4499,7120 - true (3)
9107,2387,3559,3488 - false (2)
9045,4425,3559,4490 - false (0)
From what I understand, the best way to do this, is by using a 2d-array, and I've managed to get the file imported successfully:
Scanner in = null;
try {
in = new Scanner(new File("areas.txt"));
} catch (FileNotFoundException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
List < String[] > lines = new ArrayList < > ();
while ( in .hasNextLine()) {
String line = in .nextLine().trim();
String[] splitted = line.split(", ");
lines.add(splitted);
}
String[][] result = new String[lines.size()][];
for (int i = 0; i < result.length; i++) {
result[i] = lines.get(i);
}
System.out.println(Arrays.deepToString(result));
The result I get:
[[9045,9107,2376,9017], [2387,4405,4499,7120], [9107,2376,3559,3488], [9045,4405,3559,4499], [], []]
From here I'm a bit stuck on checking the codes individually per line. Any suggestions or advice? Is the 2d-array the best way of doing this, or is there maybe an easier or better way of doing it?
The expected number of inputs defines the type of searching algorithm you should use.
If you aren't searching through thousands of lines then a simple algorithm will do just fine. When in doubt favour simplicity over complex and hard to understand algorithms.
While it is not an efficient algorithm, in most cases a simple nested for-loop will do the trick.
A simple implementation would look like this:
final int FOUND_THRESHOLD = 2;
String[] comparedCodes = {"9107", "4405", "2387", "4499"};
String[][] allInputs = {
{"9045", "9107", "2376", "9017"}, // This should not match
{"2387", "4405", "4499", "7120"}, // This should match
{"9107", "2376", "3559", "3488"}, // This should not match
{"9045", "4405", "3559", "4499"}, // This should match
};
List<String[] > results = new ArrayList<>();
for (String[] input: allInputs) {
int numFound = 0;
// Compare the codes
for (String code: input) {
for (String c: comparedCodes) {
if (code.equals(c)) {
numFound++;
break; // Breaking out here prevents unnecessary work
}
}
if (numFound >= FOUND_THRESHOLD) {
results.add(input);
break; // Breaking out here prevents unnecessary work
}
}
}
for (String[] result: results) {
System.out.println(Arrays.toString(result));
}
which provides us with the output:
[2387, 4405, 4499, 7120]
[9045, 4405, 3559, 4499]
To expand on my comment, here's a rough outline of what you could do:
String textFieldContents = ... //get it
//build a set of the user input by splitting at commas
//a stream is used to be able to trim the elements before collecting them into a set
Set<String> userInput = Arrays.stream(textFieldContents .split(","))
.map(String::trim).collect(Collectors.toSet());
//stream the lines in the file
List<Boolean> matchResults = Files.lines(Path.of("areas.txt"))
//map each line to true/false
.map(line -> {
//split the line and stream the parts
return Arrays.stream(line.split(","))
//trim each part
.map(String::trim)
//select only those contained in the user input set
.filter(part -> userInput.contains(part))
//count matching elements and return whether there are more than 2 or not
.count() > 2l;
})
//collect the results into a list, each element position should correspond to the zero-based line number
.collect(Collectors.toList());
If you need to collect the matching lines instead of a flag per line you could replace map() with filter() (same content) and change the result type to List<String>.
I've created a function to print values from an ArrayList and it works, however, it prints them left to right and I want them to be printed top to bottom.
My method for doing this is here:
ArrayList<Integer> scoresFromRounds = new ArrayList<Integer>();
public String printSortedScoreList()
{
sortScoreList();
String scores = scoresFromRounds.toString();
return scores;
}
I've looked around and this kind of thing seems to be working for others:
for (Object o : exes)
System.out.println(o);
However, when I tried to do it like
for (Integer score : scoresFromRounds)
{
}
I'm not entirely sure what to put in the body of the for each, as I need this function to return a String as I then use it to display the scores within a label, and labels only accept Strings.
Does anyone have any idea on how I could achieve this?
Thanks
Edit:
By top to bottom, I mean something like
10
20
30
40
50
Maybe this is what you are looking for
StringBuilder response = new StringBuilder();
String newLine = "\n";
for (Integer integer : scoresFromRounds) {
response.append(integer);
response.append(newLine);
}
return respone;
This will print the result top to bottom
I don't know for sure, but maybe the line you are looking for is some variation of
System.out.println(Integer.toString(score));
Edit: if you want to have the String elsewhere, then do:
String x = Integer.toString(score); System.out.println(x);
I would suggest Java Stream API version of the solution.
public String print(Collection<Integer> collection) {
return collection.stream()
.map(Object::toString) // convert integers to strings
.collect(Collectors.joining(System.lineSeparator())); // join them
}
I have to put in a string array some values resulting from several parsed html pages. So the first value it's a name and all the others are numbers. After I must return the array to main to print. Obviously I make something wrong .
this is part of my newbie code...
String[] ret = null;
int y = 0;
for (Element h1 : h1s) {
// Using Jsoup to scrape the html file and find H1 text
h1_id = h1.className();
// I put here the text of H1
h1_text = h1.text();
if (h1_id.equals("ezomat-logo-text ezCSS")) {
// jump to the next h1
} else {
// I want to put the txt as the first array place
ret[y] = "'" + h1_text + "'";
}
i = 0;
// found the number values single integers with comma
for (Element image : images) {
Imm[i] = "," + imageName;
i++;
}
i = 0;
y = 1;
// y = 1 because I want to start from the second position.
for (Element image : images) {
ret[y] = Imm[i];
i++;
y++;
}
}
return ret;
You can't dynamicly resize an array, you have to initialize it with a fixed size.
So, you have to initialize it with
String[] ret = new String[size];
where size have to be the number of elements you are going to put into your array.
Or the better approach: Use ArrayList<String>instead. Initialize it with
ArrayList<String> ret = new ArrayList<String>();
and add your Items with ret.add("whatever");.
On the first line of your code you attempt to define an array without a size, but you don't actually define it, you just assign null.
Also, it's impossible to dynamically add elements to such array.
For these scenarios we have List.
To define a List that stores Strings use the following code:
List<String> ret = new ArrayList<String> ();
And then proceed to add elements to this array like so:
ret.add ("," + imageName);
To retrieve a value from an index in the list do the following:
ret.get(index);
Java does not allow arrays with variable length. I think that this is your main problem.
There are two choiches:
Obtain the array length first and instantiate the array accordingly
String[] ret = new String[100];
Use an ArrayList
ArrayList<String> ret = new ArrayList<String>();
You can add elements to the ArrayList like this: ret.add(value);
The Java Tutorial: Arrays
java.util.ArrayList reference
App reads TextEdit value to String and then converts to ArrayList. But before converting it removes spaces between words in TextEdit. So after converting I get ArrayList size only 1.
So my question is how to get the real size. I am using ArrayList because of its swap() function.
outputStream.setText("");
stream = inputStream.getText().toString().replace(" ", "");
key = Integer.parseInt(inputKey.getText().toString());
List<String> arrayList = Arrays.asList(stream);
int lenght = arrayList.size();
if (key < lenght)
{
outputStream.append(lenght+"\n");
outputStream.append("OK");
}
else {
outputStream.append(lenght+"\n");
outputStream.append("Error");
}
}
stream = inputStream.getText().toString();
key = Integer.parseInt(inputKey.getText().toString());
List<String> arrayList = new ArrayList<String>();
for (String x : stream.split(" ")) arrayList.add(x);
int lenght = arrayList.size();
if (key < lenght)
{
outputStream.append(lenght+"\n");
outputStream.append("OK");
}
else {
outputStream.append(lenght+"\n");
outputStream.append("Error");
}
That is my guess at what you actually wanted to do...
The size and the length are different things.
You try to get the size when you want the length.
Use arrayList[0].length() instead of your arrayList.size().
If you want to parse your String to an Array try:
List<String> arrayList = Arrays.asList(stream.split(","));
(this example expects that your text is a comma separated list)
Arrays.asList() expect an array as paramter not just a String. A String is like an array of String of size 1 thats why your list is always of size 1. If you want to Store the words of your String use :
Arrays.asList(stream.split(" ")); //Don't use replace method anymore
When I use System.out.println to show the size of a vector after calling the following method then it shows 1 although it should show 2 because the String parameter is "7455573;photo41.png;photo42.png" .
private void getIdClientAndPhotonames(String csvClientPhotos)
{
Vector vListPhotosOfClient = new Vector();
String chainePhotos = "";
String photoName = "";
String photoDirectory = new String(csvClientPhotos.substring(0, csvClientPhotos.indexOf(';')));
chainePhotos = csvClientPhotos.substring(csvClientPhotos.indexOf(';')+1);
chainePhotos = chainePhotos.substring(0, chainePhotos.lastIndexOf(';'));
if (chainePhotos.indexOf(';') == -1)
{
vListPhotosOfClient.addElement(new String(chainePhotos));
}
else // aaa;bbb;...
{
for (int i = 0 ; i < chainePhotos.length() ; i++)
{
if (chainePhotos.charAt(i) == ';')
{
vListPhotosOfClient.addElement(new String(photoName));
photoName = "";
continue;
}
photoName = photoName.concat(String.valueOf(chainePhotos.charAt(i)));
}
}
}
So the vector should contain the two String photo41.png and photo42.png , but when I print the vector content I get only photo41.png.
So what is wrong in my code ?
The answer is not valid for this question anymore, because it has been retagged to java-me. Still true if it was Java (like in the beginning): use String#split if you need to handle csv files.
It's be far easier to split the string:
String[] parts = csvClientPhotos.split(";");
This will give a string array:
{"7455573","photo41.png","photo42.png"}
Then you'd simply copy parts[1] and parts[2] to your vector.
You have two immediate problems.
The first is with your initial manipulation of the string. The two lines:
chainePhotos = csvClientPhotos.substring(csvClientPhotos.indexOf(';')+1);
chainePhotos = chainePhotos.substring(0, chainePhotos.lastIndexOf(';'));
when applied to 7455573;photo41.png;photo42.png will end up giving you photo41.png.
That's because the first line removes everything up to the first ; (7455573;) and the second strips off everything from the final ; onwards (;photo42.png). If your intent is to just get rid of the 7455573; bit, you don't need the second line.
Note that fixing this issue alone will not solve all your ills, you still need one more change.
Even though your input string (to the loop) is the correct photo41.png;photo42.png, you still only add an item to the vector each time you encounter a delimiting ;. There is no such delimiter at the end of that string, meaning that the final item won't be added.
You can fix this by putting the following immediately after the for loop:
if (! photoName.equals(""))
vListPhotosOfClient.addElement(new String(photoName));
which will catch the case of the final name not being terminated with the ;.
These two lines are the problem:
chainePhotos = csvClientPhotos.substring(csvClientPhotos.indexOf(';') + 1);
chainePhotos = chainePhotos.substring(0, chainePhotos.lastIndexOf(';'));
After the first one the chainePhotos contains "photo41.png;photo42.png", but the second one makes it photo41.png - which trigers the if an ends the method with only one element in the vector.
EDITED: what a mess.
I ran it with correct input (as provided by the OP) and made a comment above.
I then fixed it as suggested above, while accidently changing the input to 7455573;photo41.png;photo42.png; which worked, but is probably incorrect and doesn't match the explanation above input-wise.
I wish someone would un-answer this.
You can split the string manually. If the string having the ; symbol means why you can do like this? just do like this,
private void getIdClientAndPhotonames(String csvClientPhotos)
{
Vector vListPhotosOfClient = split(csvClientPhotos);
}
private vector split(String original) {
Vector nodes = new Vector();
String separator = ";";
// Parse nodes into vector
int index = original.indexOf(separator);
while(index>=0) {
nodes.addElement( original.substring(0, index) );
original = original.substring(index+separator.length());
index = original.indexOf(separator);
}
// Get the last node
nodes.addElement( original );
return nodes;
}