Say I have a string that may look like:
"RAHDTWUOPO"
I know the word I'm looking for, for example:
"WORD"
what would be the best method for finding if I can make up "WORD" with a string like "RAHDTWUOPO"
EDIT:
Because of this question being unclear Id thought Id put more detail. What I wanted to achieve was to find if a word I knew beforehand could be made up from a random string of letters. Wasn't sure how to go about this, with a loop or if there was some other method.
I had come up with something quickly in my head but I knew it was to much effort, but I'll put it here to make this question more clearer of what I wanted to achieve.
public class MyLetterObject {
private String letter;
private Boolean used;
public String getText() {
return letter;
}
public void setLetter(String letter) {
this.letter = letter;
}
public Boolean getUsed() {
return used;
}
public void setUsed(Boolean used) {
this.used = used;
}
}
boolean ContainsWord(String Word, String RandomLetterString) {
List<MyLetterObject> MyLetterList = new ArrayList<MyLetterObject>();
for (char ch : RandomLetterString.toCharArray()) {
MyLetterObject mlo = new MyLetterObject();
mlo.setLetter(String.valueOf(ch));
mlo.setUsed(false);
MyLetterList.add(mlo);
}
String sMatch = "";
for (char Wordch : Word.toCharArray()) {
for (MyLetterObject o : MyLetterList) {
if (o.getUsed() == false
&& String.valueOf(Wordch).equals(o.getText())) {
o.setUsed(true);
sMatch = sMatch + String.valueOf(Wordch);
break;
}
}
}
if (sMatch.equals(Word)) {
return true;
} else {
return false;
}
}
As you can see to much effort. Evgeniy Dorofeev answer is much more better for the purpose of just finding if a word can be made from a string made up of letters in a random order.
try
boolean containsWord(String s, String w) {
List<Character> list = new LinkedList<Character>();
for (char c : s.toCharArray()) {
list.add(c);
}
for (Character c : w.toCharArray()) {
if (!list.remove(c)) {
return false;
}
}
return true;
}
You search every letter, one by one in the first String.
String randomString = "RAHDTWUOPO";
String word = "WORD";
for(int i=0;i<word.length; i++){
if(randomString.contains(word.charAt(i))){
// Yey, another letter found
}
}
Then you only have to test if for every i the letter was actually found, if not, the word is not included in the randomString.
You need find, that all letters from your word "WORD" exists in input string at list once.
Simple loop will do it for you but performance will not be best one.
You can use guava library multiset:
http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained
Multiset wordsMultiset = HashMultiset.create();wordsMultiset.addAll(words);// now we can use wordsMultiset.count(String) to find the count of a word
This example is about words, adopte it to chars of your input string.
Related
I periodically check if a string which I get from a web service changed. This works just fine but if an old string is deleted from my method triggers, too.
For Example:
//I get this at the beginning
"One,Two,Three"
//And at the next check I get this
"Two,Three"
So the String changed and my method returned true like it is supposed to do.
But I only want to return true if e.g. "Four" is added to the string.
Can anyone give me a solution for this problem?
Thank you a lot,
Freezed
if (!oldstring.contains(newstring)))
return true;
Perhaps you could use split like so
public class MyClass {
public static void main(String args[]) {
String oldString = "This,Is,A,Test";
String[] oldItems = oldString.split(",");
String newString = "This,Is,A,New";
String[] newItems = newString.split(",");
// For each new item, check all old items
for (String newItem: newItems)
{
Boolean foundItem = false;
for (String oldItem: oldItems)
{
// Item was already in the old items
if (newItem.equals(oldItem))
{
foundItem = true;
break;
}
}
// New item is not in the old list of items
if (!foundItem)
{
System.out.println("New item added: " + newItem);
}
}
}
}
Something like
newString.contains(oldString) && !newString.equals(oldString)
Why not just trigger when the length of the string increases? The question doesn't state that what is being added matters--only whether something is being added at all.
boolean result = false;
if(newString.length() > oldString.length()) {
result = true;
break;
}
return result;
EDIT: Based on further clarification, I understand that the length of the string is not the best indicator, since something can be removed and added at the same time, in which case OP wants true returned--even if length is shorter. Here's a solution that splits the strings into tokens, and then checks whether the last token of the old string occurs before the last token of the new string, because that means something was added after it:
boolean result = false;
String delim = ",";
String oldStringTokens[] = oldString.split(delim);
String newStringTokens[] = newString.split(delim);
for(int i = 0; i < newStringTokens.length; i++) {
if(oldStringTokens[oldStringTokens.length-1].equals(newStringTokens[i])) {
if(i < newStringTokens.length - 1) {
result = true;
}
}
}
return result;
So i'm using IntelliJ and the replace buzzword is highlighted. Most of the tips are over my head so i ignore them, but what i got for this one was that the result of string.replace is ignored. Why?
would i need something like ( string = string.replace(string.charAt(i));)?
import java.util.Scanner;
public class PhoneNumberDecipher {
public static String phoneNumber;
public static String Decipher(String string) {
string = phoneNumber;
for(int i =0; i<=phoneNumber.length(); i++) {
if(string.equalsIgnoreCase("A")
||string.equalsIgnoreCase("B")
||string.equalsIgnoreCase("C")) {
string.replace(string.charAt(i),'2')
}
else if(string.equalsIgnoreCase("D")
||string.equalsIgnoreCase("E")
||string.equalsIgnoreCase("F")) {
string.replace(string.charAt(i),'3');
}
else if(string.equalsIgnoreCase("G")
||string.equalsIgnoreCase("H")
||string.equalsIgnoreCase("I")) {
string.replace(string.charAt(i),'4');
}
else if(string.equalsIgnoreCase("J")
||string.equalsIgnoreCase("K")
||string.equalsIgnoreCase("L")) {
string.replace(string.charAt(i),'5');
}
else if(string.equalsIgnoreCase("M")
||string.equalsIgnoreCase("N")
||string.equalsIgnoreCase("O")) {
string.replace(string.charAt(i),'6');
}
else if(string.equalsIgnoreCase("P")
||string.equalsIgnoreCase("Q")
||string.equalsIgnoreCase("R")
|| string.equalsIgnoreCase("S")) {
string.replace(string.charAt(i),'7');
}
else if(string.equalsIgnoreCase("T")
||string.equalsIgnoreCase("U")
||string.equalsIgnoreCase("V")) {
string.replace(string.charAt(i),'8');
}
else if(string.equalsIgnoreCase("W")
||string.equalsIgnoreCase("X")
||string.equalsIgnoreCase("Y")
||string.equalsIgnoreCase("Z")) {
string.replace(string.charAt(i),'9');
}
}
return string;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please Enter a Phone Number you Wish to Decipher...");
phoneNumber = input.nextLine();
System.out.print(Decipher(phoneNumber));
}
}
String objects are immutable.
From the docs:
public String replace(char oldChar,char newChar)
Returns a string resulting from replacing all occurrences of oldChar in this string with newChar.
Hope this helps.
IntelliJ is complaining that you're calling a method whose only effect is to return a value (String.replace) but you're ignoring that value. The program isn't doing anything at the moment because you're throwing away all the work it does.
You need to use the return value.
There are other bugs in there too. You might be able to progress a little further if you use some of this code:
StringBuilder convertedPhoneNumber = new StringBuilder();
// Your loop begins here
char curCharacter = phoneNumber.charAt(i);
if (curCharacter == 'a') {
convertedPhoneNumber.append("2");
}
// More conditional logic and rest of loop goes here.
return convertedPhoneNumber.toString();
I had the same problem, but i did it like this:
String newWord = oldWord.replace(oldChar,newChar);
use that statement
string = string.replace(string.charAt(i));
Why? String is an immutable object. Look at this thread to get a complete explanation. This a fundemental part of Java, so make sure you learn it well.
string = string.replace(string.charAt(i), '<The char to replace>') will work.
Refer to this article you might understand better:
https://alvinalexander.com/blog/post/java/faq-why-isnt-replace-replaceall-replacefirst-not-working/
Since string is immutable, you have to reassign the a string with the string.replace() string.
Here is the function i wrote. it take a Stringbuffer text then assign v[0]=text[0] , then starts from text[1] >>>text[n-1] the comparing. The vector v should contain the characters. I don't know where is the problem. Can you help me?
public void setdirectory(StringBuffer text)
{
String temp;
boolean t;
v.add(0,String.valueOf(text.charAt(0))); //A[0]=first letter in text.
for(int i=1;i<text.length();++i)
{
temp=String.valueOf(text.charAt(i));
try{
for(int j=0;j<v.capacity();++j)
{
if(!temp.equals(v.elementAt(j)))
{
v.add(i,temp);
}
v.trimToSize();
}
// System.out.println(v.capacity());
}catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("usage error");
}
}
}
If you're using Java 8+, then it might be simpler to use the new Stream API...
String str = "aabbc";
StringBuilder sb = new StringBuilder(str.length());
str.chars().distinct().forEach(c -> sb.append((char)c));
System.out.println(sb.toString());
Which prints
abc
I'd write a function to get unique characters, and assuming you need to preserve the insertion order, I'd use a LinkedHashSet<Character> and I'd prefer StringBuilder over StringBuffer. Something like
static String getUniqueCharacters(String text) {
Set<Character> set = new LinkedHashSet<>();
for (char ch : text.toCharArray()) {
set.add(ch);
}
StringBuilder sb = new StringBuilder();
for (char ch : set) {
sb.append(ch);
}
return sb.toString();
}
An alternative Java 8 solution is:
String str = "aabbc";
String str2 = str.chars().distinct().mapToObj(j->""+(char)j).collect(Collectors.joining());
System.out.println(str2);
Behind the scenes, this is similar to other answers here as IntStream::distinct is implemented using a LinkedHashSet<Integer>, and joining uses a StringBuilder.
You need to keep track of where you are adding your value in the vector. Also the number of objects in a vector is size(), not capacity() (look up the API for both; capacity() shows the current number of 'spaces' filled and available to fill before the vector needs to expand, it doesn't show how much of it has actually been filled).
Doh, and the third reason your code would not have worked: you were adding the character every time it found a non-matching one in the vector (over-writing itself each time so you would have only seen the last addition)
public void setdirectory(StringBuffer text) {
String temp;
boolean t;
int addAt = 0;
v.add(addAt,String.valueOf(text.charAt(0))); //A[0]=first letter in text.
for(int i=1;i<text.length();++i) {
temp=String.valueOf(text.charAt(i));
try {
boolean found = false
for(int j=0;j<v.size();++j) {
if(temp.equals(v.elementAt(j))) {
found = true;
break;
}
}
if (!found) {
addAt++;
v.add(addAt,temp);
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("usage error");
}
}
}
And although this would fix your code as it stands (which will be an important exercise for a beginner programmer), there are other ways of doing this that you should explore.
I want to identify the elements in letters and elements in numbers in String array.Is there any other way to do it?
String a[]={"aaaa","111111","bbbbbb"};
for(int i=0;i<a.length;i++)
{
post your code for this FOR LOOP
}
They say that you have a problem... so you choose regular expressions to solve it, now you have two problems. :-)
However, if speed is not that much of an issue, you could attempt it, assuming you have good unit tests in place. Something along the lines of:
public static void testRegularExpressionForElement() {
String[] a = new String[] {"test1", "13", "blah", "1234.44"};
Pattern pattern = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+");
for (String element : a) {
if (pattern.matcher(element).matches()) {
System.out.println(element + " is a number");
} else {
System.out.println(element + " is not a number");
}
}
}
What's nice about the above, is that you can adapt the expression to match exactly what you want.
Another approach would be is to use Integer.parseInt() and catching the exceptions, but this is bad programming as you're using exceptions for logic.
Traverse the array and write a function to check isNumeric or not.
for (a1 : a){
boolean isNumbr= isNumeric(a1);
}
...
public static boolean isNumeric(String str)
{
try
{
double d = Double.parseDouble(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
What is the most elegant way to convert a hyphen separated word (e.g. "do-some-stuff") to the lower camel-case variation (e.g. "doSomeStuff") in Java?
Use CaseFormat from Guava:
import static com.google.common.base.CaseFormat.*;
String result = LOWER_HYPHEN.to(LOWER_CAMEL, "do-some-stuff");
With Java 8 there is finally a one-liner:
Arrays.stream(name.split("\\-"))
.map(s -> Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase())
.collect(Collectors.joining());
Though it takes splitting over 3 actual lines to be legible ツ
(Note: "\\-" is for kebab-case as per question, for snake_case simply change to "_")
The following method should handle the task quite efficient in O(n). We just iterate over the characters of the xml method name, skip any '-' and capitalize chars if needed.
public static String toJavaMethodName(String xmlmethodName) {
StringBuilder nameBuilder = new StringBuilder(xmlmethodName.length());
boolean capitalizeNextChar = false;
for (char c:xmlMethodName.toCharArray()) {
if (c == '-') {
capitalizeNextChar = true;
continue;
}
if (capitalizeNextChar) {
nameBuilder.append(Character.toUpperCase(c));
} else {
nameBuilder.append(c);
}
capitalizeNextChar = false;
}
return nameBuilder.toString();
}
Why not try this:
split on "-"
uppercase each word, skipping the first
join
EDIT: On second thoughts... While trying to implement this, I found out there is no simple way to join a list of strings in Java. Unless you use StringUtil from apache. So you will need to create a StringBuilder anyway and thus the algorithm is going to get a little ugly :(
CODE: Here is a sample of the above mentioned aproach. Could someone with a Java compiler (sorry, don't have one handy) test this? And benchmark it with other versions found here?
public static String toJavaMethodNameWithSplits(String xmlMethodName)
{
String[] words = xmlMethodName.split("-"); // split on "-"
StringBuilder nameBuilder = new StringBuilder(xmlMethodName.length());
nameBuilder.append(words[0]);
for (int i = 1; i < words.length; i++) // skip first
{
nameBuilder.append(words[i].substring(0, 1).toUpperCase());
nameBuilder.append(words[i].substring(1));
}
return nameBuilder.toString(); // join
}
If you don't like to depend on a library you can use a combination of a regex and String.format. Use a regex to extract the starting characters after the -. Use these as input for String.format. A bit tricky, but works without a (explizit) loop ;).
public class Test {
public static void main(String[] args) {
System.out.println(convert("do-some-stuff"));
}
private static String convert(String input) {
return String.format(input.replaceAll("\\-(.)", "%S"), input.replaceAll("[^-]*-(.)[^-]*", "$1-").split("-"));
}
}
Here is a slight variation of Andreas' answer that does more than the OP asked for:
public static String toJavaMethodName(final String nonJavaMethodName){
final StringBuilder nameBuilder = new StringBuilder();
boolean capitalizeNextChar = false;
boolean first = true;
for(int i = 0; i < nonJavaMethodName.length(); i++){
final char c = nonJavaMethodName.charAt(i);
if(!Character.isLetterOrDigit(c)){
if(!first){
capitalizeNextChar = true;
}
} else{
nameBuilder.append(capitalizeNextChar
? Character.toUpperCase(c)
: Character.toLowerCase(c));
capitalizeNextChar = false;
first = false;
}
}
return nameBuilder.toString();
}
It handles a few special cases:
fUnnY-cASe is converted to funnyCase
--dash-before-and--after- is converted to dashBeforeAndAfter
some.other$funky:chars? is converted to someOtherFunkyChars
For those who has com.fasterxml.jackson library in the project and don't want to add guava you can use the jaskson namingStrategy method:
new PropertyNamingStrategy.SnakeCaseStrategy.translate(String);
get The Apache commons jar for StringUtils. Then you can use the capitalize method
import org.apache.commons.lang.StringUtils;
public class MyClass{
public String myMethod(String str) {
StringBuffer buff = new StringBuffer();
String[] tokens = str.split("-");
for (String i : tokens) {
buff.append(StringUtils.capitalize(i));
}
return buff.toString();
}
}
As I'm not a big fan of adding a library just for one method, I implemented my own solution (from camel case to snake case):
public String toSnakeCase(String name) {
StringBuilder buffer = new StringBuilder();
for(int i = 0; i < name.length(); i++) {
if(Character.isUpperCase(name.charAt(i))) {
if(i > 0) {
buffer.append('_');
}
buffer.append(Character.toLowerCase(name.charAt(i)));
} else {
buffer.append(name.charAt(i));
}
}
return buffer.toString();
}
Needs to be adapted depending of the in / out cases.
In case you use Spring Framework, you can use provided StringUtils.
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.stream.Collectors;
public class NormalizeUtils {
private static final String DELIMITER = "_";
private NormalizeUtils() {
throw new IllegalStateException("Do not init.");
}
/**
* Take name like SOME_SNAKE_ALL and convert it to someSnakeAll
*/
public static String fromSnakeToCamel(final String name) {
if (StringUtils.isEmpty(name)) {
return "";
}
final String allCapitalized = Arrays.stream(name.split(DELIMITER))
.filter(c -> !StringUtils.isEmpty(c))
.map(StringUtils::capitalize)
.collect(Collectors.joining());
return StringUtils.uncapitalize(allCapitalized);
}
}
Iterate through the string. When you find a hypen, remove it, and capitalise the next letter.