How to format a string with a variable number of arguments - java

Lets say I have a method which returns a list with a random number of random numbers - we will call that method List<Integer> getRandomNumberOfRandomNumbers();
System.out.println(String.format("Here are the random numbers: %s", getRandomNumberOfRandomNumbers()));
I know this won't work but how can I achieve this effect?
Example Output
Here are the random numbers:
1 4 2 4
Here are the random numbers:
2 43 323 434 3423 54

It's easiest to just make getRandomNumberOfRandomNumbers return all of the numbers in a single String. Or you could do it all inline, like this:
getRandomNumberOfRandomNumbers().stream()
.map(Object::toString)
.collect(Collectors.joining(" "));

For example, if we have a List of Integers as below:
List<Integer> var = new ArrayList<>();
var.add(1);
var.add(4);
var.add(2);
var.add(4);
Then to print the List in your desired way, you can follow this:
System.out.println(String.format("Here are the random numbers:%n%n%s",
var.toString().replaceAll("[,\\[,\\]]", "")));
This outputs:
Here are the random numbers:
1 4 2 4
Here var is the list your function getRandomNumberOfRandomNumbers() is returning and we are converting it to String using var.toString() but it returns [1, 4, 2, 4]. So, we need to remove [, ] and ,. I used regular expression to replace them with an empty character. This is actually simple and easy way but not sure whether it is an efficient way!! Whenever i need to convert a Colletion to String, i use toString() method and then do some trick with regular expression to get my desired form of representation.
Update: After surfing web, i found few alternatives. (Preferred over my previous answer using List.toString())
StringJoiner : a relevant answer in SO
For example, in your case, you can do:
StringJoiner sj = new StringJoiner(" ");
for (Integer i : var) {
sj.add(String.valueOf(i));
}
System.out.println(sj.toString());
You can do the same with the following two alternatives.
StringUtils : a relevant answer in SO
String.Join : requires CharSequence

Another solution is iterating through the list and adding the values to a string builder before printing it out
like so:
StringBuilder stringBuilder = new StringBuilder();
for(Integer number : getRandomNumberOfRandomNumbers())
stringBuilder.append(number + " ");
System.out.println("Here are the random numbers: " + stringBuilder.toString().trim());

Related

Hashmap in for loop not reading all the input

This is for AOC day 2. The input is something along the lines of
"6-7 z: dqzzzjbzz
13-16 j: jjjvjmjjkjjjjjjj
5-6 m: mmbmmlvmbmmgmmf
2-4 k: pkkl
16-17 k: kkkkkkkkkkkkkkkqf
10-16 s: mqpscpsszscsssrs
..."
It's formatted like 'min-max letter: password' and seperated by line. I'm supposed to find how many passwords meet the minimum and maximum requirements. I put all that prompt into a string variable and used Pattern.quote("\n") to seperate the lines into a string array. This worked fine. Then, I replaced all the letters except for the numbers and '-' by making a pattern Pattern.compile("[^0-9]|-"); and running that for every index in the array and using .trim() to cut off the whitespace at the end and start of each string. This is all working fine, I'm getting the desired output like 6 7 and 13 16.
However, now I want to try and split this string into two. This is my code:
HashMap<Integer,Integer> numbers = new HashMap<Integer,Integer>();
for(int i = 0; i < inputArray.length; i++){
String [] xArray = x[i].split(Pattern.quote(" "));
int z = Integer.valueOf(xArray[0]);
int y = Integer.valueOf(xArray[1]);
System.out.println(z);
System.out.println(y);
numbers.put(z, y);
}
System.out.println(numbers);
So, first making a hasmap which will store <min, max> values. Then, the for loop (which runs 1000 times) splits every index of the 6 7 and 13 16 string into two, determined by the " ". The System.out.println(z); and System.out.println(y); are working as intended.
6
7
13
16
...
This output goes on to give me 2000 integers seperated by a line each time. That's exactly what I want. However, the System.out.println(numbers); is outputting:
{1=3, 2=10, 3=4, 4=7, 5=6, 6=9, 7=12, 8=11, 9=10, 10=18, 11=16, 12=13, 13=18, 14=16, 15=18, 16=18, 17=18, 18=19, 19=20}
I have no idea where to even start with debugging this. I made a test file with an array that is formatted like "even, odd" integers all the way up to 100. Using this exact same code (I did change the variable names), I'm getting a better output. It's not exactly desired since it starts at 350=351 and then goes to like 11=15 and continues in a non-chronological order but at least it contains all the 100 keys and values.
Also, completely unrelated question but is my formatting of the for loop fine? The extra space at the beginning and the end of the code?
Edit: I want my expected output to be something like {6=7, 13=16, 5=6, 2=4, 16=17...}. Basically, the hashmap would have the minimum and maximum as the key and value and it'd be in chronological order.
The problem with your code is that you're trying to put in a nail with a saw. A hashmap is not the right tool to achieve what you want, since
Keys are unique. If you try to input the same key multiple times, the first input will be overwritten
The order of items in a HashMap is undefined.
A hashmap expresses a key-value-relationship, which does not exist in this context
A better datastructure to save your Passwords would probably just be a ArrayList<IntegerPair> where you would have to define IntegerPair yourself, since java doesn't have the notion of a type combining two other types.
I think you are complicating the task unnecessarily. I would proceed as follows:
split the input using the line separator
for each line remove : and split using the spaces to get an array with length 3
build from the array in step two
3.1. the min/max char count from array[0]
3.2 charachter classes for the letter and its negation
3.3 remove from the password all letters that do not correspond to the given one and check if the length of the password is in range.
Something like:
public static void main(String[] args){
String input = "6-7 z: dqzzzjbzz\n" +
"13-16 j: jjjvjmjjkjjjjjjj\n" +
"5-6 m: mmbmmlvmbmmgmmf\n" +
"2-4 k: pkkl\n" +
"16-17 k: kkkkkkkkkkkkkkkqf\n" +
"10-16 s: mqpscpsszscsssrs\n";
int count = 0;
for(String line : input.split("\n")){
String[] temp = line.replace(":", "").split(" "); //[6-7, z, dqzzzjbzz]
String minMax = "{" + (temp[0].replace('-', ',')) + "}"; //{6,7}
String letter = "[" + temp[1] + "]"; //[z]
String letterNegate = "[^" + temp[1] + "]"; //[^z]
if(temp[2].replaceAll(letterNegate, "").matches(letter + minMax)){
count++;
}
}
System.out.println(count + "passwords are valid");
}

Convert String to int array in Java the fast way

does anyone know a faster way to convert string to int array?
Java V7
The format given is "4 343 234 -24" and so on. Spaces between the numbers, amount of numbers is known beforhand just as is the range within the numbers are
long[] array = new long[length];
for (int i = 0; i < length - 1; i++) {
array[i] = Integer.parseInt(n.substring(0, n.indexOf(' ')));
n = n.substring(n.substring(0, n.indexOf(' ')).length() + 1);
}
array[length - 1] = Integer.parseInt(n);
Using String.split() is by far the most efficient when you want to split by a single character (a space, in your case).
If you are aiming for maximal efficiency when splitting by spaces, then this would be a good solution:
List<Integer> res = new ArrayList<>();
Arrays.asList(kraft.split(" ")).forEach(s->res.add(Integer.parseInt(s)));
Integer[] result = res.toArray(new Integer[0]);
And this works for any number of numbers.
Splitting the input with the pattern \\s+ would handle one or more white-space characters, not only spaces, appearing between the numbers.
Stream.of(input.split("\\s+")).mapToInt(Integer::parseInt).toArray();
The mapToInt method returns an IntStream which provides the toArray method. This method returns an array containing the elements of the IntStream.
if You are using Java8 or higher version then you can get your expected output by writing this single line of code.
String str= "4 343 234 -24";
int[] intArr=Stream.of(str.split(" ")).mapToInt(Integer::parseInt).toArray();
System.out.println(Arrays.toString(intArr));

Parsing & Replacing Values in a String

Questions like this one have been answered but none helped me understand and decide the best suited way to do this in my case.
The idea:
Input: 15k+5b-1m
Ouput: 15000+5000000000-1000000
Basically replacing k by 1,000 - m by 1,000,000 and b by 1,000,000,000 and multiply it to the value it is attached to.
How I thought I'd do it:
Using 2 StringTokenizer, one to parse math signs +,-,*,/ and one to parse
letter k,m,b that I call on every element the first parser got.
So if we apply the algorithm we'd have for my example:
Str Input = 15k+5b-1m
StringTokenizer math_token= new StringTokenizer(source, Input);
while (math_token.hasMoreTokens())
{
while(math_token.hasMoreElements())
{
Str token_value = math_token.nextElement();
parse_letters(token_value) and change values...
}
math_token.nextToken();
format stuff for the final string
}
So it goes like:
15k -> 15 -> 15000
If I understand your question, then you could replace b with nine zeros m with six zeros and k with three zeros. Also, by convention, Java variable names start with a lower-case letter. Something like,
String input = "15k+5b-1m";
input = input.replace("b", "000000000").replace("m", "000000")
.replace("k", "000");
System.out.println(input);
which outputs (as requested)
15000+5000000000-1000000

Exporting specific pattern of string using split method in a most efficient way

I want to export pattern of bit stream in a String varilable. Assume our bit stream is something like bitStream="111000001010000100001111". I am looking for a Java code to save this bit stream in a specific array (assume bitArray) in a way that all continous "0"s or "1"s be saved in one array element. In this example output would be somethins like this:
bitArray[0]="111"
bitArray[1]="00000"
bitArray[2]="1"
bitArray[3]="0"
bitArray[4]="1"
bitArray[5]="0000"
bitArray[6]="1"
bitArray[7]="0000"
bitArray[8]="1111"
I want to using bitArray to calculate the number of bit which is stored in each continous stream. For example in this case the final output would be, "3,5,1,1,1,4,1,4,4". I figure it out that probably "split" method would solve this for me. But I dont know what splitting pattern would do that for me, if i Using bitStream.split("1+") it would split on contious "1" pattern, if i using bitStream.split("0+") it will do that base on continous"0" but how it could be based on both?
Mathew suggested this solution and it works:
var wholeString = "111000001010000100001111";
wholeString = wholeString.replace('10', '1,0');
wholeString = wholeString.replace('01', '0,1');
stringSplit = wholeString.split(',');
My question is "Is this solution the most efficient one?"
Try replacing any occurrence of "01" and "10" with "0,1" and "1,0" respectively. Then once you've injected the commas, split the string using the comma as the delimiting character.
String wholeString = "111000001010000100001111"
wholeString = wholeString.replace("10", "1,0");
wholeString = wholeString.replace("01", "0,1");
String stringSplit[] = wholeString.split(",");
You can do this with a simple regular expression. It matches 1s and 0s and will return each in the order they occur in the stream. How you store or manipulate the results is up to you. Here is some example code.
String testString = "111000001010000100001111";
Pattern pattern = Pattern.compile("1+|0+");
Matcher matcher = pattern.matcher(testString);
while (matcher.find())
{
System.out.print(matcher.group().length());
System.out.print(" ");
}
This will result in the following output:
3 5 1 1 1 4 1 4 4
One option for storing the results is to put them in an ArrayList<Integer>
Since the OP wanted most efficient, I did some tests to see how long each answer takes to iterate over a large stream 10000 times and came up with the following results. In each test the times were different but the order of fastest to slowest remained the same. I know tick performance testing has it's issues like not accounting for system load but I just wanted a quick test.
My answer completed in 1145 ms
Alessio's answer completed in 1202 ms
Matthew Lee Keith's answer completed in 2002 ms
Evgeniy Dorofeev's answer completed in 2556 ms
Hope this helps
I won't give you a code, but I'll guide you to a possible solution:
Construct an ArrayList<Integer>, iterate on the array of bits, as long as you have 1's, increment a counter and as soon as you have 0, add the counter to the ArrayList. After this procedure, you'll have an ArrayList that contain numbers, etc: [1,2,2,3,4] - Representing a serieses of 1's and 0's.
This will represent the sequences of 1's and 0's. Then you construct an array of the size of the ArrayList, and fill it accordingly.
The time complexity is O(n) because you need to iterate on the array only once.
This code works for any String and patterns, not only 1s and 0s. Iterate char by char, and if the current char is equal to the previous one, append the last char to the last element of the List, otherwise create a new element in the list.
public List<String> getArray(String input){
List<String> output = new ArrayList<String>();
if(input==null || input.length==0) return output;
int count = 0;
char [] inputA = input.toCharArray();
output.add(inputA[0]+"");
for(int i = 1; i <inputA.length;i++){
if(inputA[i]==inputA[i-1]){
String current = output.get(count)+inputA[i];
output.remove(count);
output.add(current);
}
else{
output.add(inputA[i]+"");
count++;
}
}
return output;
}
try this
String[] a = s.replaceAll("(.)(?!\\1)", "$1,").split(",");
I tried to implement #Maroun Maroun solution.
public static void main(String args[]){
long start = System.currentTimeMillis();
String bitStream ="0111000001010000100001111";
int length = bitStream.length();
char base = bitStream.charAt(0);
ArrayList<Integer> counts = new ArrayList<Integer>();
int count = -1;
char currChar = ' ';
for (int i=0;i<length;i++){
currChar = bitStream.charAt(i);
if (currChar == base){
count++;
}else {
base = currChar;
counts.add(count+1);
count = 0;
}
}
counts.add(count+1);
System.out.println("Time taken :" + (System.currentTimeMillis()-start ) +"ms");
System.out.println(counts.toString());
}
I believe it is more effecient way, as he said it is O(n) , you are iterating only once. Since the goal to get the count only not to store it as array. i woul recommen this. Even if we use Regular Expression ( internal it would have to iterate any way )
Result out put is
Time taken :0ms
[1, 3, 5, 1, 1, 1, 4, 1, 4, 4]
Try this one:
String[] parts = input.split("(?<=1)(?=0)|(?<=0)(?=1)");
See in action here: http://rubular.com/r/qyyfHNAo0T

Print array without brackets and commas

I'm porting a Hangman game to Android and have met a few problems. The original Java program used the console, so now I have to somehow beautify the output so that it fits my Android layout.
How do I print an array without the brackets and commas? The array contains slashes and gets replaced one-by-one when the correct letter is guessed.
I am using the usual .toString() function of the ArrayList class and my output is formatted like: [ a, n, d, r, o, i, d ]. I want it to simply print out the array as a single String.
I fill the array using this bit of code:
List<String> publicArray = new ArrayList<>();
for (int i = 0; i < secretWordLength; i++) {
hiddenArray.add(secretWord.substring(i, i + 1));
publicArray.add("-");
}
And I print it like this:
TextView currentWordView = (TextView) findViewById(R.id.CurrentWord);
currentWordView.setText(publicArray.toString());
Replace the brackets and commas with empty space.
String formattedString = myArrayList.toString()
.replace(",", "") //remove the commas
.replace("[", "") //remove the right bracket
.replace("]", "") //remove the left bracket
.trim(); //remove trailing spaces from partially initialized arrays
Basically, don't use ArrayList.toString() - build the string up for yourself. For example:
StringBuilder builder = new StringBuilder();
for (String value : publicArray) {
builder.append(value);
}
String text = builder.toString();
(Personally I wouldn't call the variable publicArray when it's not actually an array, by the way.)
For Android, you can use the join method from android.text.TextUtils class like:
TextUtils.join("",array);
first
StringUtils.join(array, "");
second
Arrays.asList(arr).toString().substring(1).replaceFirst("]", "").replace(", ", "")
EDIT
probably the best one: Arrays.toString(arr)
With Java 8 or newer, you can use String.join, which provides the same functionality:
Returns a new String composed of copies of the CharSequence elements joined together with a copy of the specified delimiter
String[] array = new String[] { "a", "n", "d", "r", "o", "i", "d" };
String joined = String.join("", array); //returns "android"
With an array of a different type, one should convert it to a String array or to a char sequence Iterable:
int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };
//both of the following return "1234567"
String joinedNumbers = String.join("",
Arrays.stream(numbers).mapToObj(String::valueOf).toArray(n -> new String[n]));
String joinedNumbers2 = String.join("",
Arrays.stream(numbers).mapToObj(String::valueOf).collect(Collectors.toList()));
The first argument to String.join is the delimiter, and can be changed accordingly.
If you use Java8 or above, you can use with stream() with native.
publicArray.stream()
.map(Object::toString)
.collect(Collectors.joining(" "));
References
Use Java 8 Language Features
JavaDoc StringJoiner
Joining Objects into a String with Java 8 Stream API
the most simple solution for removing the brackets is,
convert the arraylist into string with .toString() method.
use String.substring(1,strLen-1).(where strLen is the length of string after conversion from arraylist).
the result string is your string with removed brackets.
I have used
Arrays.toString(array_name).replace("[","").replace("]","").replace(", ","");
as I have seen it from some of the comments above, but also i added an additional space character after the comma (the part .replace(", ","")), because while I was printing out each value in a new line, there was still the space character shifting the words. It solved my problem.
I used join() function like:
i=new Array("Hi", "Hello", "Cheers", "Greetings");
i=i.join("");
Which Prints:
HiHelloCheersGreetings
See more: Javascript Join - Use Join to Make an Array into a String in Javascript
String[] students = {"John", "Kelly", "Leah"};
System.out.println(Arrays.toString(students).replace("[", "").replace("]", " "));
//output: John, Kelly, Leah
You can use the reduce method provided for streams for Java 8 and above.Note you would have to map to string first to allow for concatenation inside of reduce operator.
publicArray.stream().map(String::valueOf).reduce((a, b) -> a + " " + b).get();
I was experimenting with ArrayList and I also wanted to remove the Square brackets after printing the Output and I found out a Solution. I just made a loop to print Array list and used the list method " myList.get(index) " , it works like a charm.
Please refer to my Code & Output below:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ArrayList mylist = new ArrayList();
Scanner scan = new Scanner(System.in);
for(int i = 0; i < 5; i++) {
System.out.println("Enter Value " + i + " to add: ");
mylist.add(scan.nextLine());
}
System.out.println("=======================");
for(int j = 0; j < 5; j++) {
System.out.print(mylist.get(j));
}
}
}
OUTPUT
Enter Value 0 to add:
1
Enter Value 1 to add:
2
Enter Value 2 to add:
3
Enter Value 3 to add:
4
Enter Value 4 to add:
5
=======================
12345
Just initialize a String object with your array
String s=new String(array);

Categories