I have a two dimensional string array look like this:
The first column contains characters of many strings, other columns are extra data for character. I want to search a string (maybe change to array character) in this array to get all match indexes (start - end). For example, when I search with key "next", the result should be [5 - 8], [13 - 16] (the highlight parts in image above). Shortly, I need a method look like this:
public static List<Interval> search(String searchText, String[][] data, int columnsCount, int rowCount){
// Convert search text to String array
String[] searchArr = getStringArray(searchText);
// then search in data
}
// where Interval is:
public class Interval{
public int start;
public int end;
}
Is there any fast way to search like this,cause my data is very large?
Thanks in advance!
I would recommend to adapt the String[][] to a CharSequence. Then you are free to do everything you can do with a CharSequence and this also means that you can use java.util.regex.Matcher to search for the string and you don't need to implement an own search algorithm.
For example:
public class Main {
public static void main(String[] args) {
String[][] array2d = createArray();
int charSeqColumn = 0;
CharSequence charSequnce = new Array2DColumnCharSequnce(array2d, charSeqColumn);
System.out.println(charSequnce.toString());
Pattern patttern = Pattern.compile("ext");
Matcher matcher = patttern.matcher(charSequnce);
while (matcher.find()) {
String matchGroup = matcher.group();
int start = matcher.start();
int end = matcher.end() - 1;
String msg = MessageFormat.format("{0} matched at: [{1}] - [{2}]", matchGroup, start, end);
System.out.println(msg);
}
}
private static String[][] createArray() {
String[][] array2d = new String[2][10];
array2d[0][0] = "N";
array2d[0][1] = "e";
array2d[0][2] = "x";
array2d[0][3] = "t";
array2d[0][4] = " ";
array2d[0][5] = "N";
array2d[0][6] = "e";
array2d[0][7] = "x";
array2d[0][8] = "t";
array2d[0][9] = " ";
array2d[1][0] = "H";
array2d[1][1] = "e";
array2d[1][2] = "l";
array2d[1][3] = "l";
array2d[1][4] = "o";
array2d[1][5] = "W";
array2d[1][6] = "o";
array2d[1][7] = "r";
array2d[1][8] = "l";
array2d[1][9] = "d";
return array2d;
}
}
will output
Next Next
ext matched at: [1] - [3]
ext matched at: [6] - [8]
I would implement the CharSequence adaption like this
class Array2DColumnCharSequnce implements CharSequence {
private int column;
private String[][] array2d;
private int endIndex;
private int startIndex;
public Array2DColumnCharSequnce(String[][] array2d, int column) {
this(array2d, column, 0, array2d[column].length);
this.array2d = array2d;
this.column = column;
}
public Array2DColumnCharSequnce(String[][] array2d, int column,
int startIndex, int endIndex) {
this.array2d = array2d;
this.column = column;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
public int length() {
return endIndex - startIndex;
}
public char charAt(int index) {
String charString = array2d[column][startIndex + index];
return charString.charAt(0);
}
public CharSequence subSequence(int start, int end) {
Array2DColumnCharSequnce array2dColumnCharSequnce = new Array2DColumnCharSequnce(
array2d, column, start, end);
return array2dColumnCharSequnce;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder(this);
return sb.toString();
}
}
Note:
The Array2DColumnCharSequnce is just a quick implementation and it does not address exception handling yet nor it addresses what happens when there are more than one char in a string column.
Why to use a CharSequence decorator
The difference with adapting the array to a CharSequence to other approaches is that you use a standard java interface that can be re-used with many other classes and thus is very flexible.
Some often used standard java classes that take a CharSequence as parameter
String.contains(CharSequence s)
String.contentEquals(CharSequence cs)
String.replace(CharSequence target, CharSequence replacement)
Appendable.append(CharSequence csq)
StringBuffer.append(CharSequence s)
StringBuilder.append(CharSequence s)
See the full list here.
Use the code above and try this to see how flexibe the decorator is.
public static void main(String[] args) {
String[][] array2d = createArray();
CharSequence charSequnce = new Array2DColumnCharSequnce(array2d, 0);
boolean contentEquals = "Next Next ".contentEquals(charSequnce);
System.out.println(contentEquals);
CharSequence column1CharSequnce = new Array2DColumnCharSequnce(array2d, 1);
String replaced = "I want to say Next Next ".replace(charSequnce, column1CharSequnce);
System.out.println(replaced);
}
will output
true
I want to say HelloWorld
Finally everyone has to decide what he/she wants and what fits the situation. I prefer implementations that give me more options if I can get them "almost" for free.
It is similar to search a subString in a String.
e.g.
A B C D N E X T J H J N E N E X T O
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
So the answer should be [4-7] and [13-16].
public static List<Integer> findIndexes(String source, String toFind){
List<Integer> list = new LinkedList<Integer>();//it will return the starting indexes of the found substring, we can easily find the end e=index by adding the length of the other.
int start = 0;
while(start < source.length()){
if(source.charAt(start)==toFind.charAt(0)){//if the char is same then find whether the whole toFind string is present or not.
if(isMatch(source, toFind, start)){//if it is found than increment the source pointer to the end after the toFind string
list.add(start);
start = start+toFind.length();
continue;
}
}
start++;
}
return list;
}
private static boolean isMatch(String s1, String s2, int srcIndex){
int desIndex = 0;
while(desIndex<s2.length() && s1.charAt(srcIndex)==s2.charAt(desIndex)){
srcIndex++;
desIndex++;
}
if(desIndex==s2.length()){
return true;
}
return false;
}
And sample driver program:
public static void main(String[] args) {
String s1="abcdnextponexnextpour";
String s2 = "next";
List<Integer> list = findIndexes(s1, s2);
for(int i : list){
System.out.println(i);
}
}
It will output the indexes:
4
13
i.e. you can add the length of the toFind String to calculate the last index.
This is your solution:
void main(String a[][],String k){
String m="";
for(int i=0;i<a.length;i++)
m+=a[i][0];
int n=0,x;
while(n<m.length()){
n=m.indexOf(k,n);
x=n+k.length();
System.out.println(n+"-"+x);
n=x;
}
}
void main(String a[][],char k){
for(int i=0;i <a.length;i++)
if(a[i][0]==k)System.out.println(i);
}
it extracts the first strings of the dda and searches it.
you may generate the value n and x as class interval and include it in list.
I would implement search as follows -
public static List<Interval> search(
String searchText, String[][] data) {
List<Interval> al = new ArrayList<>();
if (searchText != null) {
searchText = searchText.trim().toUpperCase();
char[] toMatch = searchText.toCharArray();
for (int i = 0; i < data.length; i++) {
if (data[i] != null && data.length > i
&& data[i].length > 0
&& data[i][0].charAt(0) == toMatch[0]) {
boolean matched = true;
for (int t = 1; t < toMatch.length; t++) {
if (i + t > data.length
|| data[i + t][0].charAt(0) != toMatch[t]) {
i += (t - 1);
matched = false;
break;
}
}
if (matched) {
Interval interval = new Interval();
interval.start = i - 1;
interval.end = interval.start + (toMatch.length - 1);
al.add(interval);
}
}
}
}
return al;
}
And, I would modify Interval to add a toString() like this
public String toString() {
return String.valueOf(start) + "-" + end;
}
Finally, to test it I would use this main method.
public static void main(String[] args) {
String[][] test = { { "N" }, { "A" }, { "N" },
{ "A" }, { "T" }, { "A" }, { "N" }, { "E" },
{ "X" }, { "T" }, { "E" }, { "R" }, { "N" },
{ "B" }, { "N" }, { "E" }, { "X" }, { "T" } };
List<Interval> al = search("next", test);
for (Interval i : al) {
System.out.println(i);
}
}
And I did receive this output -
5-8
13-16
Related
Replace a given string at given index with list of words.
The problem statement goes below, can someone give me some intuition or idea how to proceed on this?
//A replacement class similar to Linked List
class Replacement {
int start;
String before;
String after;
//Method to replace the words
public static String replaceRanges(String text, List<Replacement> replacements) {
//TODO your code here
return null;
}
}
/* below is the example of the problem
Example #1:
Input:
text = "num foo"
replacements = [
{start: 0, before: "num", after: "String"},
{start: 4, before: "foo", after: "bar"}
]
Output:
replaceRanges(text, replacements) returns:
"String bar"
Example #2: Input: text = "num_fooBar", Output: "String_barBar"
*/
If you have your replacements sorted from smallest index to highest, you can iterate the list from last to first and search for substrings in input string and replace them if they match
public static String replaceRanges(String text, List<Replacement> replacements) {
StringBuilder s = new StringBuilder(text);
for (int i = replacements.size() - 1; i>=0; i--) {
Replacement r = replacements.get(i);
int begin = r.start;
int end = r.start + r.before.length();
if (begin >= 0 && begin < s.length() && end >= 0 && end <= s.length()) {
if (s.substring(begin, end).equals(r.before)) {
s.replace(begin, end, r.after);
}
}
}
return s.toString();
}
If your list is not sorted, you need to sort it first using Collections.sort().
I used this code for testing:
public static void main(String[] args) {
List<Replacement> replacements = List.of(
new Replacement(0, "num", "String"),
new Replacement(4, "foo", "bar"));
System.out.println(replaceRanges("num foo", replacements)); // Output: String bar
System.out.println(replaceRanges("num_fooBar", replacements)); // Output: String_barBar
System.out.println(replaceRanges("num_f", replacements)); // Output: String_f
System.out.println(replaceRanges("", replacements)); // Output:
System.out.println(replaceRanges("foonum", replacements)); // Output: foonum
}
You could replace your original string one by one and keep in mind that you have to shift the start position (because you could replace the small substring to the bigger substring)
public String replaceRanges(String text, List<Replacement> replacements) {
for(int i = 0; i < replacements.size(); i++) {
Replacement replacement = replacements.get(i);
String firstPart = text.substring(0, replacement.start);
String secondPart = text.substring(replacement.start, text.length());
String updatedSecondPart = secondPart.replace(replacement.before, replacement.after);
text = firstPart + updatedSecondPart;
updateStart(i + 1, replacements, updatedSecondPart.length() - secondPart.length());
}
return text;
}
privat void updateStart(int startIndex, List<Replacement> replacements, int shift) {
for( int i = startIndex; i < replacements.size(); i++) {
Replacement r = replacements.get(i);
r.start += shift;
}
}
Using this method you can process:
Replacement r1 = new Replacement(0, "hi", "Hello");
Replacement r2 = new Replacement(2, "lo", "p");
Sting result = replaceRanges("hi louie!", asList(r1, r2)); //result = 'Hello puie!'
How to reverse String in place in Java
input String : 1234
Output Should : 4321
what i have tried.
public static void main(String args[])
{
String number = "1234";
System.out.println("original String: " + number); String reversed = inPlaceReverse(number);
System.out.println("reversed String: " + reversed);
}
public static String inPlaceReverse(final String input)
{
final StringBuilder builder = new StringBuilder(input);
int length = builder.length();
for (int i = 0; i < length / 2; i++)
{
final char current = builder.charAt(i);
final int otherEnd = length - i - 1;
builder.setCharAt(i, builder.charAt(otherEnd)); // swap
builder.setCharAt(otherEnd, current);
}
return builder.toString();
}
i am getting answer like:
reversed String: 4231 as i expected 4321.
If your teacher wants to see your work then you should manipulate the chars directly. Something like the following should be enough to let you spot the mistake:
public static String reverse(String orig)
{
char[] s = orig.toCharArray();
final int n = s.length;
final int halfLength = n / 2;
for (int i=0; i<halfLength; i++)
{
char temp = s[i];
s[i] = s[n-1-i];
s[n-1-i] = temp;
}
return new String(s);
}
It can be even simpler using StringBuilder's reverse() function:
public static String inPlaceReverse(String input) {
StringBuilder builder = new StringBuilder(input);
return builder.reverse().toString();
}
public static String inPlaceReverse(String number) {
char[] ch = number.toCharArray();
int i = 0;
int j = number.length()-1;
while (i < j) {
char temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
i++;
j--;
}
return String.valueOf(ch);
}
1. Using Character Array:
public String reverseSting(String inputString) {
char[] inputStringArray = inputString.toCharArray();
String reverseString = "";
for (int i = inputStringArray.length - 1; i >= 0; i--) {
reverseString += inputStringArray[i];
}
return reverseString;
}
2. Using StringBuilder:
public String reverseSting(String inputString) {
StringBuilder stringBuilder = new StringBuilder(inputString);
stringBuilder = stringBuilder.reverse();
return stringBuilder.toString();
}
OR
return new StringBuilder(inputString).reverse().toString();
This is an interview question.
Reverse a String in place :
public class Solution4 {
public static void main(String[] args) {
String a = "Protijayi";
System.out.println(reverse(a)); //iyajitorP
}
private static String reverse(String a) {
char[] ca = a.toCharArray();
int start = 0 ; int end = a.length()-1;
while(end > start) {
swap(ca,start,end);
start++;
end--;
}//while
return new String(ca);
}
private static void swap(char[] ca, int start, int end) {
char t = ca[start];
ca[start] = ca[end];
ca[end] = t ;
}
}
Mind also, that you can avoid using additional memory during the swap, though having some extra computation.
public class StringReverser {
public static String reverseStringInPlace(String toReverse) {
char[] chars = toReverse.toCharArray();
int inputStringLength = toReverse.length();
for (int i = 0; i < inputStringLength / 2; i++) {
int toMoveBack = toReverse.charAt(i);
int toMoveForward = toReverse.charAt(inputStringLength - i - 1);
//swap
toMoveForward = toMoveBack - toMoveForward;
toMoveBack -= toMoveForward;
toMoveForward += toMoveBack;
chars[i] = (char) toMoveBack;
chars[inputStringLength - i - 1] = (char) toMoveForward;
}
return String.valueOf(chars);
}
public static void main(String[] args) {
System.out.println(reverseStringInPlace("asd0")); // output: 0dsa
System.out.println(reverseStringInPlace("sd0")); // output: 0ds
System.out.println(reverseStringInPlace("")); // output: empty
System.out.println(reverseStringInPlace("-")); // output: -
System.out.println(reverseStringInPlace("ABD+C")); // output: C+DBA
System.out.println(reverseStringInPlace("勒")); // output: 勒
System.out.println(reverseStringInPlace("分歧。")); // output: 。歧分
System.out.println(reverseStringInPlace("Marítimo")); // output: omitíraM
}
}
Relevant to swap discussion can be found here:
How to swap two numbers without using temp variables or arithmetic operations?
Convert the string to a character array first and then use recursion.
public void reverseString(char[] s) {
helper(0, s.length - 1, s);
}
private void helper(int left, int right, char[] s){
if(left >= right) {
return;
}
char temp = s[left];
s[left++] = s[right];
s[right--] = temp;
helper(left, right, s);
}
So with the input [1,2,3,4], the helper function will be called as follows :
1. helper(0, 3, [1,2,3,4]), Swap 1 and 4
2. helper(1, 2, [1,2,3,4]), Swap 2 and 3
3. helper(2, 1, [1,2,3,4]) Terminates, left is now greater than right
After converting into char array. Just swap the both ends ( first index, last index) and move towards each other(first index to last index and from last index to first) until the crossing.
public void reverseString(char[] s) {
int start = 0;
int end = s.length-1;
char temp = ' ';
while((start)<(end)){
temp = s[start];
s[start] = s[end];
s[end] = temp;
start++;
end--;
}
System.out.println(s);
}
So I have run into a problem where I have an ArrayList where the List is comprised of one letter strings. In this case (A,B,C,D,F,J,N) where the size of the list is 7.
Now I am trying to write code making all combinations of lettering that can be made where the order does not matter i.e. (I know it will be involving "n choose k") up to 5 letters long.
So for 7 choose 1 will be A,B,C,D,F,J,N
... 7 choose 2 ... etc.
... 7 choose 3 ... etc.
... etc.
I am then looking to store these string combinations into another list/hashmap (haven't decided on yet).
But my main focus is on the code that would generate such strings. If anyone can help that would be greatly appreciated. I also want to make it modular just in case i want to eventually form other combinations of 6,7 length. (Which is why I am not just doing it with 5 loops and incrementing for different indices).
What I have so far...
public class ReadFile {
public static void main(String[] args) throws IOException {
String file_name = "C:/Users/Shane/Documents/College/Classes/PurchaseTable.txt";
extract(file_name, 50);
}
private String path;
public ReadFile(String file_path) {
path= file_path;
}
public String[] OpenFile() throws IOException {
FileReader fr = new FileReader(path);
BufferedReader textReader = new BufferedReader(fr);
int numberOfLines = readLines();
String[] textData = new String[numberOfLines];
int i;
for(i=0; i < numberOfLines; i++) {
textData[i] = textReader.readLine();
}
textReader.close();
return textData;
}
int readLines() throws IOException {
FileReader file_to_read = new FileReader(path);
BufferedReader bf = new BufferedReader(file_to_read);
String aLine;
int numberOfLines = 0;
while(( aLine = bf.readLine()) != null) {
numberOfLines++;
}
bf.close();
return numberOfLines;
}
public static void extract(String filename, int threshold) {
String file_name = filename;
ArrayList<String> temp = new ArrayList<String>();
ArrayList<String> products = new ArrayList<String>();
HashMap<Integer, String> productsPerDate = new HashMap<Integer, String>();
//HashMap<Integer, String> allCombinations = new HashMap<Integer, String>();
try {
ReadFile file = new ReadFile(file_name);
String[] aryLines = file.OpenFile();
int i;
for (i=1; i < aryLines.length; i++) { //excludes header section of any table as shown in assignment
temp.add(aryLines[i]);
}
}
catch (IOException e) {
System.out.println( e.getMessage() );
}
System.out.println(temp);
System.out.println(temp.get(0));
System.out.println(temp.size());
int i; int j; int l;
for (i=0; i<temp.size(); i++) {
String str = temp.get(i);
StringBuilder sb = new StringBuilder(str);
int k =0;
for (j=0; j<=sb.length(); j++) {
if(sb.charAt(j) == '\"' && k==0) {
sb.delete(0, j+1);
k++;
}
if(sb.charAt(j) == '\"' && k!=0) {
sb.delete(j, sb.length());
String line = null;
System.out.println(sb);
for( l=0; l<sb.length(); l++) {
String string = Character.toString(sb.charAt(l));
if(string.equals(",")) {
}
else if (l ==0) {
products.add(string);
line = string;
}
else {
products.add(string);
line = line + string;
}
}
productsPerDate.put(i, line);
//System.out.println(products);
break;
}
}
}
System.out.println(products);
System.out.println(productsPerDate.entrySet()); //Hashmap set to string of 1 letter characters for products per date
Set<String> removeDup = new HashSet<>();
removeDup.addAll(products);
products.clear();
products.addAll(removeDup);
System.out.println(products);
int maxLength = productsPerDate.get(0).length();
for(int m = 0; m < productsPerDate.size(); m++) { //determine max length of string in hashmap
if(maxLength < productsPerDate.get(m).length()) {
maxLength = productsPerDate.get(m).length();
}
}
This probably isn't the most efficient way to do this but please bear with me and help in any way you can.
The output is shown below of what has been created in the above code:
1,"A,B,C,N",1/3/2013
4
A,B,C,N
B,C,D,A,F
A,C,V,N,J
A,C,J,D
[A, B, C, N, B, C, D, A, F, A, C, V, N, J, A, C, J, D]
[0=ABCN, 1=BCDAF, 2=ACVNJ, 3=ACJD]
[A, B, C, D, F, V, J, N]
So essentially I am trying to write the code to make all the possible combinations of length 5 string using the letter strings contained in the array list shown in last output.
Here is a little method that returns a list of all letter combinations of length k (order doesn't matter), given an input String of length n:
public static ArrayList<String> combinations(String nChars, int k) {
int n = nChars.length();
ArrayList<String> combos = new ArrayList<String>();
if (k == 0) {
combos.add("");
return combos;
}
if (n < k || n == 0)
return combos;
String last = nChars.substring(n-1);
combos.addAll(combinations(nChars.substring(0, n-1), k));
for (String subCombo : combinations(nChars.substring(0, n-1), k-1))
combos.add(subCombo + last);
return combos;
}
public static void main(String[] args) {
String nChars = "ABCDE";
System.out.println(combinations(nChars, 2));
}
output: [AB, AC, BC, AD, BD, CD, AE, BE, CE, DE]
I used Strings as input and output, since they are immutable and more well-behaved with regard to slicing than Lists. But if your List contains only 1-letter Strings, it should be easy to convert.
I don't know if this recursive implementation is performant, but it reflects nicely the mathematical property of the Pascal triangle: (n choose k) = (n-1 choose k-1) + (n-1 choose k)
Brute force, without recursion, with generics, not optimized, didactic.
If you want arrangements rather than combinaisons, just comment one line.
// COMBINAISONS
/**
* Return combinaisons of input
* #param _input
* #param _n how many to pick
* #return
*/
public static <T> Vector<Vector<T>> combinaisons (Vector<T> _input, int _n)
{
Vector<Vector<T>> output=new Vector<Vector<T>> ();
int size=_input.size();
// Current result
Object current[]=new Object[_n];
Arrays.fill(current,"");
// which element we take at each box (between 0 and size-1)
int current_indices[]=new int[_n];
Arrays.fill(current_indices,-1);
// inputs used
boolean used[]=new boolean [size];
Arrays.fill(used, false);
// Which box are we processing
int current_box=0;
// Next value for next position
int next_pos_value=0;
// ALGORITHM
while (true)
{
// Finished ?
if (current_box<0)
break;
// Last element ?
if (current_box>=_n)
{
// => save group
output.add(new Vector<T>((List<T>) Arrays.asList(current)));
current_box--;
continue;
}
// filling Current box > 0 && < _n
// next value available
int last_value=current_indices[current_box];
int next_value=-1;
// Where do we begin
int begin_test=0;
if (last_value>=0)
begin_test=last_value+1;
// bigger
// comment this for arrangement rather than combinaisons
if (begin_test<next_pos_value) begin_test=next_pos_value;
for (int test_value=begin_test; test_value < size; test_value++)
if (!used[test_value])
{
next_value=test_value;
break;
}
// VALUE AVAILABLE
if (next_value!=-1)
// valid value ?
{
// release
if (last_value!=-1)
used[last_value]=false;
used[next_value]=true;
current_indices[current_box]=next_value;
current[current_box]=_input.get(next_value);
// next position
current_box++;
// like arrangements, but next value always more
next_pos_value=next_value+1;
continue;
}
else
// invalid value (too big) ?
{
// release
if (last_value!=-1)
used[last_value]=false;
current_indices[current_box]=-1;
// back position
current_box--;
// like arrangements, but reset this
next_pos_value=-1;
continue;
}
}
return output;
}
// public static Vector<Vector<T>> combinaisons (Vector<T> _input)
I am new to Java Strings the problem is that I want to count the Occurrences of a specific word in a String. Suppose that my String is:
i have a male cat. the color of male cat is Black
Now I dont want to split it as well so I want to search for a word that is "male cat". it occurs two times in my string!
What I am trying is:
int c = 0;
for (int j = 0; j < text.length(); j++) {
if (text.contains("male cat")) {
c += 1;
}
}
System.out.println("counter=" + c);
it gives me 46 counter value! So whats the solution?
You can use the following code:
String in = "i have a male cat. the color of male cat is Black";
int i = 0;
Pattern p = Pattern.compile("male cat");
Matcher m = p.matcher( in );
while (m.find()) {
i++;
}
System.out.println(i); // Prints 2
Demo
What it does?
It matches "male cat".
while(m.find())
indicates, do whatever is given inside the loop while m finds a match.
And I'm incrementing the value of i by i++, so obviously, this gives number of male cat a string has got.
If you just want the count of "male cat" then I would just do it like this:
String str = "i have a male cat. the color of male cat is Black";
int c = str.split("male cat").length - 1;
System.out.println(c);
and if you want to make sure that "female cat" is not matched then use \\b word boundaries in the split regex:
int c = str.split("\\bmale cat\\b").length - 1;
StringUtils in apache commons-lang have CountMatches method to counts the number of occurrences of one String in another.
String input = "i have a male cat. the color of male cat is Black";
int occurance = StringUtils.countMatches(input, "male cat");
System.out.println(occurance);
Java 8 version:
public static long countNumberOfOccurrencesOfWordInString(String msg, String target) {
return Arrays.stream(msg.split("[ ,\\.]")).filter(s -> s.equals(target)).count();
}
Java 8 version.
System.out.println(Pattern.compile("\\bmale cat")
.splitAsStream("i have a male cat. the color of male cat is Black")
.count()-1);
This static method does returns the number of occurrences of a string on another string.
/**
* Returns the number of appearances that a string have on another string.
*
* #param source a string to use as source of the match
* #param sentence a string that is a substring of source
* #return the number of occurrences of sentence on source
*/
public static int numberOfOccurrences(String source, String sentence) {
int occurrences = 0;
if (source.contains(sentence)) {
int withSentenceLength = source.length();
int withoutSentenceLength = source.replace(sentence, "").length();
occurrences = (withSentenceLength - withoutSentenceLength) / sentence.length();
}
return occurrences;
}
Tests:
String source = "Hello World!";
numberOfOccurrences(source, "Hello World!"); // 1
numberOfOccurrences(source, "ello W"); // 1
numberOfOccurrences(source, "l"); // 3
numberOfOccurrences(source, "fun"); // 0
numberOfOccurrences(source, "Hello"); // 1
BTW, the method could be written in one line, awful, but it also works :)
public static int numberOfOccurrences(String source, String sentence) {
return (source.contains(sentence)) ? (source.length() - source.replace(sentence, "").length()) / sentence.length() : 0;
}
using indexOf...
public static int count(String string, String substr) {
int i;
int last = 0;
int count = 0;
do {
i = string.indexOf(substr, last);
if (i != -1) count++;
last = i+substr.length();
} while(i != -1);
return count;
}
public static void main (String[] args ){
System.out.println(count("i have a male cat. the color of male cat is Black", "male cat"));
}
That will show: 2
Another implementation for count(), in just 1 line:
public static int count(String string, String substr) {
return (string.length() - string.replaceAll(substr, "").length()) / substr.length() ;
}
Why not recursive ?
public class CatchTheMaleCat {
private static final String MALE_CAT = "male cat";
static int count = 0;
public static void main(String[] arg){
wordCount("i have a male cat. the color of male cat is Black");
System.out.println(count);
}
private static boolean wordCount(String str){
if(str.contains(MALE_CAT)){
count++;
return wordCount(str.substring(str.indexOf(MALE_CAT)+MALE_CAT.length()));
}
else{
return false;
}
}
}
public class TestWordCount {
public static void main(String[] args) {
int count = numberOfOccurences("Alice", "Alice in wonderland. Alice & chinki are classmates. Chinki is better than Alice.occ");
System.out.println("count : "+count);
}
public static int numberOfOccurences(String findWord, String sentence) {
int length = sentence.length();
int lengthWithoutFindWord = sentence.replace(findWord, "").length();
return (length - lengthWithoutFindWord)/findWord.length();
}
}
This will work
int word_count(String text,String key){
int count=0;
while(text.contains(key)){
count++;
text=text.substring(text.indexOf(key)+key.length());
}
return count;
}
Replace the String that needs to be counted with empty string and then use the length without the string to calculate the number of occurrence.
public int occurrencesOf(String word)
{
int length = text.length();
int lenghtofWord = word.length();
int lengthWithoutWord = text.replace(word, "").length();
return (length - lengthWithoutWord) / lenghtofWord ;
}
Once you find the term you need to remove it from String under process so that it won't resolve the same again, use indexOf() and substring() , you don't need to do contains check length times
The string contains that string all the time when looping through it. You don't want to ++ because what this is doing right now is just getting the length of the string if it contains " "male cat"
You need to indexOf() / substring()
Kind of get what i am saying?
If you find the String you are searching for, you can go on for the length of that string (if in case you search aa in aaaa you consider it 2 times).
int c=0;
String found="male cat";
for(int j=0; j<text.length();j++){
if(text.contains(found)){
c+=1;
j+=found.length()-1;
}
}
System.out.println("counter="+c);
This should be a faster non-regex solution.
(note - Not a Java programmer)
String str = "i have a male cat. the color of male cat is Black";
int found = 0;
int oldndx = 0;
int newndx = 0;
while ( (newndx=str.indexOf("male cat", oldndx)) > -1 )
{
found++;
oldndx = newndx+8;
}
There are so many ways for the occurrence of substring and two of theme are:-
public class Test1 {
public static void main(String args[]) {
String st = "abcdsfgh yfhf hghj gjgjhbn hgkhmn abc hadslfahsd abcioh abc a ";
count(st, 0, "a".length());
}
public static void count(String trim, int i, int length) {
if (trim.contains("a")) {
trim = trim.substring(trim.indexOf("a") + length);
count(trim, i + 1, length);
} else {
System.out.println(i);
}
}
public static void countMethod2() {
int index = 0, count = 0;
String inputString = "mynameiskhanMYlaptopnameishclMYsirnameisjasaiwalmyfrontnameisvishal".toLowerCase();
String subString = "my".toLowerCase();
while (index != -1) {
index = inputString.indexOf(subString, index);
if (index != -1) {
count++;
index += subString.length();
}
}
System.out.print(count);
}}
We can count from many ways for the occurrence of substring:-
public class Test1 {
public static void main(String args[]) {
String st = "abcdsfgh yfhf hghj gjgjhbn hgkhmn abc hadslfahsd abcioh abc a ";
count(st, 0, "a".length());
}
public static void count(String trim, int i, int length) {
if (trim.contains("a")) {
trim = trim.substring(trim.indexOf("a") + length);
count(trim, i + 1, length);
} else {
System.out.println(i);
}
}
public static void countMethod2() {
int index = 0, count = 0;
String inputString = "mynameiskhanMYlaptopnameishclMYsirnameisjasaiwalmyfrontnameisvishal".toLowerCase();
String subString = "my".toLowerCase();
while (index != -1) {
index = inputString.indexOf(subString, index);
if (index != -1) {
count++;
index += subString.length();
}
}
System.out.print(count);
}}
I've got another approach here:
String description = "hello india hello india hello hello india hello";
String textToBeCounted = "hello";
// Split description using "hello", which will return
//string array of words other than hello
String[] words = description.split("hello");
// Get number of characters words other than "hello"
int lengthOfNonMatchingWords = 0;
for (String word : words) {
lengthOfNonMatchingWords += word.length();
}
// Following code gets length of `description` - length of all non-matching
// words and divide it by length of word to be counted
System.out.println("Number of matching words are " +
(description.length() - lengthOfNonMatchingWords) / textToBeCounted.length());
Complete Example here,
package com.test;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class WordsOccurances {
public static void main(String[] args) {
String sentence = "Java can run on many different operating "
+ "systems. This makes Java platform independent.";
String[] words = sentence.split(" ");
Map<String, Integer> wordsMap = new HashMap<String, Integer>();
for (int i = 0; i<words.length; i++ ) {
if (wordsMap.containsKey(words[i])) {
Integer value = wordsMap.get(words[i]);
wordsMap.put(words[i], value + 1);
} else {
wordsMap.put(words[i], 1);
}
}
/*Now iterate the HashMap to display the word with number
of time occurance */
Iterator it = wordsMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Integer> entryKeyValue = (Map.Entry<String, Integer>) it.next();
System.out.println("Word : "+entryKeyValue.getKey()+", Occurance : "
+entryKeyValue.getValue()+" times");
}
}
}
public class WordCount {
public static void main(String[] args) {
// TODO Auto-generated method stub
String scentence = "This is a treeis isis is is is";
String word = "is";
int wordCount = 0;
for(int i =0;i<scentence.length();i++){
if(word.charAt(0) == scentence.charAt(i)){
if(i>0){
if(scentence.charAt(i-1) == ' '){
if(i+word.length()<scentence.length()){
if(scentence.charAt(i+word.length()) != ' '){
continue;}
}
}
else{
continue;
}
}
int count = 1;
for(int j=1 ; j<word.length();j++){
i++;
if(word.charAt(j) != scentence.charAt(i)){
break;
}
else{
count++;
}
}
if(count == word.length()){
wordCount++;
}
}
}
System.out.println("The word "+ word + " was repeated :" + wordCount);
}
}
Simple solution is here-
Below code uses HashMap as it will maintain keys and values. so here keys will be word and values will be count (occurance of a word in a given string).
public class WordOccurance
{
public static void main(String[] args)
{
HashMap<String, Integer> hm = new HashMap<>();
String str = "avinash pande avinash pande avinash";
//split the word with white space
String words[] = str.split(" ");
for (String word : words)
{
//If already added/present in hashmap then increment the count by 1
if(hm.containsKey(word))
{
hm.put(word, hm.get(word)+1);
}
else //if not added earlier then add with count 1
{
hm.put(word, 1);
}
}
//Iterate over the hashmap
Set<Entry<String, Integer>> entry = hm.entrySet();
for (Entry<String, Integer> entry2 : entry)
{
System.out.println(entry2.getKey() + " "+entry2.getValue());
}
}
}
public int occurrencesOf(String word) {
int length = text.length();
int lenghtofWord = word.length();
int lengthWithoutWord = text.replaceAll(word, "").length();
return (length - lengthWithoutWord) / lenghtofWord ;
}
for scala it's just 1 line
def numTimesOccurrenced(text:String, word:String) =text.split(word).size-1
I did not find anywhere an answer.. If i have: String s = "How are you"?
How can i split this into two strings, so first string containing from 0..s.length()/2 and the 2nd string from s.length()/2+1..s.length()?
Thanks!
This should do:
String s = "How are you?";
String first = s.substring(0, s.length() / 2); // gives "How ar"
String second = s.substring(s.length() / 2); // gives "e you?"
String.substring(int i) with one argument returns the substring beginning at position i
String.substring(int i, int j) with two arguments returns the substring beginning at i and ending at j-1.
(Note that if the length of the string is odd, second will have one more character than first due to the rounding in the integer division.)
String s0 = "How are you?";
String s1 = s0.subString(0, s0.length() / 2);
String s2 = s0.subString(s0.length() / 2);
So long as s0 is not null.
EDIT
This will work for odd length strings as you are not adding 1 to either index. Surprisingly it even works on a zero length string "".
You can use 'substring(start, end)', but of course check if string isn't null before:
String first = s.substring(0, s.length() / 2);
String second = s.substring(s.length() / 2);
http://www.roseindia.net/java/beginners/SubstringExample.shtml
And are you expecting string with odd length ? in this case you must add logic to handle this case correctly.
Here's a method that splits a string into n items by length. (If the string length can not exactly be divided by n, the last item will be shorter.)
public static String[] splitInEqualParts(final String s, final int n){
if(s == null){
return null;
}
final int strlen = s.length();
if(strlen < n){
// this could be handled differently
throw new IllegalArgumentException("String too short");
}
final String[] arr = new String[n];
final int tokensize = strlen / n + (strlen % n == 0 ? 0 : 1);
for(int i = 0; i < n; i++){
arr[i] =
s.substring(i * tokensize,
Math.min((i + 1) * tokensize, strlen));
}
return arr;
}
Test code:
/**
* Didn't use Arrays.toString() because I wanted to have quotes.
*/
private static void printArray(final String[] arr){
System.out.print("[");
boolean first = true;
for(final String item : arr){
if(first) first = false;
else System.out.print(", ");
System.out.print("'" + item + "'");
}
System.out.println("]");
}
public static void main(final String[] args){
printArray(splitInEqualParts("Hound dog", 2));
printArray(splitInEqualParts("Love me tender", 3));
printArray(splitInEqualParts("Jailhouse Rock", 4));
}
Output:
['Hound', ' dog']
['Love ', 'me te', 'nder']
['Jail', 'hous', 'e Ro', 'ck']
Use String.substring(int), and String.substring(int, int) method.
int cutPos = s.length()/2;
String s1 = s.substring(0, cutPos);
String s2 = s.substring(cutPos, s.length()); //which is essentially the same as
//String s2 = s.substring(cutPos);
I did not find anywhere an answer.
The first place you should always look is at the javadocs for the class in question: in this case java.lang.String. The javadocs
can be browsed online on the Oracle website (e.g. at http://download.oracle.com/javase/6/docs/api/),
are included in any Sun/Oracle Java SDK distribution,
are probably viewable in your Java IDE, and
and be found using a Google search.
public int solution(final String S, final int K) {
int splitCount = -1;
final int count = (int) Stream.of(S.split(" ")).filter(v -> v.length() > K).count();
if (count > 0) {
return splitCount;
}
final List<String> words = Stream.of(S.split(" ")).collect(Collectors.toList());
final List<String> subStrings = new ArrayList<>();
int counter = 0;
for (final String word : words) {
final StringJoiner sj = new StringJoiner(" ");
if (subStrings.size() > 0) {
final String oldString = subStrings.get(counter);
if (oldString.length() + word.length() <= K - 1) {
subStrings.set(counter, sj.add(oldString).add(word).toString());
} else {
counter++;
subStrings.add(counter, sj.add(word).toString());
}
} else {
subStrings.add(sj.add(word).toString());
}
}
subStrings.forEach(
v -> {
System.out.printf("[%s] and length %d\n", v, v.length());
}
);
splitCount = subStrings.size();
return splitCount;
}
public static void main(final String[] args) {
final MessageSolution messageSolution = new MessageSolution();
final String message = "SMSas5 ABC DECF HIJK1566 SMS POP SUV XMXS MSMS";
final int maxSize = 11;
System.out.println(messageSolution.solution(message, maxSize));
}