I have names in an array of Strings:
["foo", "bar", "baz"]
I want to transform it to be:
["foo", "foo", "bar", "bar", "baz", "baz"]
My current solution:
String[] ns = new String[2 * names.length];
int i = 0;
for (String name : names)
{
ns[i++] = name;
ns[i++] = name;
}
Is there a cleaner solution? In particular, I think the duplicated assignment is poorly done.
Assuming you are using Java 8+, you could use a Stream - flatMap every element to a two element stream and then collect to a List before converting back to an array. Like,
String[] names = { "foo", "bar", "baz" };
String[] ns = Stream.of(names).flatMap(s -> Stream.of(s, s))
.collect(Collectors.toList()).toArray(new String[] {});
A bit cleaner, perhaps:
String[] ns = new String[2 * names.length];
for (int i = 0; i < ns.length; i++)
ns[i] = names[i / 2];
Related
I have a set of JSON array :
listSession: [h0y78u93, h0y78u93, h0y78u93, h0y78u93, h0y78u93, 9i88u93, 9i88u93, 9i88u93, 9i88u93, 9i88u93]
I've created the array using the below code:
ArrayList<String> listSession = new ArrayList<String>();
for(int u=1; u < k+1; u++) {
String str = Integer.toString(u);
JSONArray arrTime=(JSONArray)mergedJSON2.get(str);
JSONObject objSession;
StringsessionName;
for (Object ro : arrTime) {
objSession = (JSONObject) ro;
sessionName = String.valueOf(objSession.get("sessionID"));
listSession.add(sessionName);
}
}
May I get your advice or opinion on how am I going to compare the value from each of the attributes in the list. If it is the same, I should it as ONE.
Meaning from the above sample, the count should be only TWO instead of TEN.
Thank You.
You can utilize Arraylist.contains() method like below:
ArrayList<String> listSession = new ArrayList<String>();
for(int u=1; u < k+1; u++) {
String str = Integer.toString(u);
JSONArray arrTime=(JSONArray)mergedJSON2.get(str);
JSONObject objSession;
StringsessionName;
for (Object ro : arrTime) {
objSession = (JSONObject) ro;
sessionName = String.valueOf(objSession.get("sessionID"));
if (!listSession.contains(sessionName)) {
listSession.add(sessionName);
}
}
}
OR
You can use a Set implementation which doesn't allow duplicate values instead of ArrayList. There's no need to compare explicitly.
// initialize
Set sessionsSet = new HashSet();
//add like below
sessionsSet.add(sessionName);
sessionsSet.size() // getting the length which should be what you expect to be 2
I would recommend to use a Set over ArrayList here. You can use ArrayList and check the list whether it contains the element and add it. ArrayList.contains() takes O(n) time because it maintains a dynamic array inside. Where as a HashSet or TreeSet can do that check in O(1) and you also don't have to do that compare yourself.
Set<String> setSession = new HashSet<String>();
for(int u=1; u < k+1; u++) {
String str = Integer.toString(u);
JSONArray arrTime=(JSONArray)mergedJSON2.get(str);
JSONObject objSession;
StringsessionName;
for (Object ro : arrTime) {
objSession = (JSONObject) ro;
sessionName = String.valueOf(objSession.get("sessionID"));
setSession.add(sessionName);
}
}
If you're okay using Java 8, then you can use shorthand implementation like this:
Example:
ArrayList<String> data = new ArrayList<String>(Arrays.asList("A", "A", "A", "B", "B", "B"));
// This will be required if your target SDK < Android N
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
List<String> uniqueData = data.stream().distinct().collect(Collectors.toList()); // Results ["A", "B"]
}
I have 2 Arrays.
One Array has Strings, which i look for.
static String[] namesToLookFor = { "NR", "STAFFELNR", "VONDATUM"};
the otherArray has Strings, which i got from a *.csv file.
indexString = indexReader.readLine();
indexArray = indexString.split(";");
My Goal is to system.out.println() the Values which are the indexArray[] and NOT in the namesToLookFor[].
For example:
namesToLookFor = {"NR"};
indexArray = {"HELLO","NR"};
//Any Algorithm here...
So in this case"HELLO" should be printed out, since it is NOT in the namesToLookFor[] Array.
If you are using java8 you can do the following
List<String> list = Arrays.asList(namesToLookFor);
Arrays.stream(indexArray)
.filter(item -> !list.contains(item))
.forEach(System.out::println);
You could iterate over your indexArray and check for each element if its contained in your namesToLookFor Array:
String[] namesToLookFor = {"NR"};
String[] indexArray = {"HELLO","NR"};
List<String> excludedNames = Arrays.asList(namesToLookFor);
for(String s : indexArray) {
if (!excludedNames.contains(s)) {
System.out.println(s);
}
}
Will output only "HELLO".
// Put array into set for better performance
Set<String> namesToFilter = new HashSet<>(Arrays.asList("NR", "STAFFELNR"));
String[] indexArray = indexReader.readLine().split(";");
// Create list with unfiltered values and remove unwanted ones
List<String> resultList = new ArrayList<>(indexArray);
resultList.removeAll(namesToFilter);
// Do with result whatever you want
for (String s : resultList)
System.out.println(s);
With Array you can use contains function but after converting it to be ArrayList, the contains function will check if the ArrayList contains a specific value.
for (int i =0; i<indexArray.length; i++) {
if (!Arrays.asList(namesToLookFor).contains(indexArray[i]))
System.out.println(indexArray[i]);
}
I've got an array of String in Java. I'd like to generate a List of String arrays that contains all the sets of String with length <=5. For example, if
String[] s1 = {"a", "b", "c", "d"}
I want the result as:
List<String[]> s2 = {{"a"}, {"b"}, {"c"}, {"d"}, {"a", "b"}, {"a", "c"}, {"a", "d"}, {"b", "c"}, {"b", "d"}, {"c", "d"}, {"a", "b", "c"}, ...}
but I can't figure out how I can generate it automatically.
You will need a K-subset algorithm implementation. I'm sure they exist in maths libraries, or you could code your own.
S1 is your set (or alphabet) and s2 is the set of subsets up to length k (5).
You have to write your own generator I guess, or use some library for permutations/combinations, there should be plenty of math libs that can do so. Example of own implementation is here:
https://codereview.stackexchange.com/questions/41510/calculate-all-possible-combinations-of-given-characters
In my opinion example in link is exactly what you need - just change input array and length. Also author puts it in one string, and I see you want to have it in array of arrays, so output also should be changed
I'll give you idea to solve this problem.
Start from an empty output string.One by one add all characters to prefix. For every character added, print all possible strings with current prefix by recursively calling for k equals to k-1.
Here K is the length in your case 1 to 5.
I used this code:
...
String[] cols = ... //linea in input
Set<String> subSet= new HashSet<String>();
Set<Set<String>> sets = new HashSet<Set<String>>();
//popolo l'insieme - escludo la data
for(int i=1; i<cols.length; i++){
subSet.add(cols[i]);
}
// creo l'insieme delle parti e popolo
sets = powerSet(subSet);
public static Set<Set<String>> powerSet(Set<String> originalSet) {
Set<Set<String>> sets = new HashSet<Set<String>>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<String>());
return sets;
}
List<String> list = new ArrayList<String>(originalSet);
String head = list.get(0);
Set<String> rest = new HashSet<String>(list.subList(1, list.size()));
for (Set<String> set : powerSet(rest)) {
if(set.size() < 5){
Set<String> newSet = new HashSet<String>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
}
return sets;
}
I'm new to Java, and I had a quick question.
I have an array named studentInfo[0] that I created from:String studentInfo[] = line.split(","); I would like to make another array from it's first index.
In other words. I have the array studentInfo that lets say looks like this:
"a,b,c,d,
a1,b1,c1,d1,
a2,b2,d2,c2 etc... "
I want another array that takes all the "a" in my other array. Example: "a,a1,a2 etc..."
How would I do this?
I have tried System.arraycopy(studentInfo, 0, array, 0, studentInfo.length); But doesn't seem to work because it does not just give me the first index.
FYI my code is in a while loop which loops every time it hits a new line. See below:
while ((line = reader.readLine()) != null) {
String studentInfo[] = line.split(",");
String array[] = new String[0];
}
Thank you!
I would do something like.
String[] studentInfoA = new String[50] //You can put the size you want.
for(int i=0; i<studentInfo.length-1; i++){
if(studentInfo[i].substring(0,1).equals("a")){
studentInfoA[i]=studentInfo[i];
}
}
i would recommend Vimsha's answer better but since you are learning i didnt want to make you struggle with collections and such, or at least i wouldnt like you to use them without properly knowing about arrays and loops.
Assuming you have this array,
studentInfo = ["a","b","c","d","a1","b1","c1","d1", "a2","b2","d2","c2"]
and you want another array like
studentInfoWithA = ["a", "a1", "a2"]
then
String studentInfo[] = new String[] { "a", "b", "c", "d", "a1", "b1", "c1", "d1", "a2", "b2", "d2", "c2" };
List<String> newList = new ArrayList<String>();
for (String info : studentInfo) {
if (info.startsWith("a")) {
newList.add(info);
}
}
String[] studentInfoWithA = newList.toArray(new String[0]);
In java 1.8, filtering looks like
String[] result = Arrays.stream(new String[] { "a","b","c","d","a1","b1","c1","d1", "a2","b2","d2","c2" })
.filter(e -> e.startsWith("a"))
.toArray(String[]::new);
Lest's say I have string:
String test= "AA BB CC BB BB CC BB";
What I would like to do is create String array like this:
String[]{"BB", "CC", "AA"}
Since B occurred 4 times C did 2 times and A only 1 time.
What would solution for this problem look like?
String test = "AA BB CC BB BB CC BB";
System.out.println(Arrays.deepToString(sort(test)));
Output: [BB, CC, AA]
Code:
public static String[] sort(String test) {
String[] strings = test.split(" ");
HashMap<String,Integer> map = new HashMap<String,Integer>();
for (String s : strings) {
Integer i = map.get(s);
if (i != null) {
map.put(s, i+1);
} else {
map.put(s, 1);
}
}
TreeMap<Integer,String> sort = new TreeMap<Integer,String>(Collections.reverseOrder());
for (Entry<String,Integer> e : map.entrySet()) {
sort.put(e.getValue(), e.getKey());
}
return sort.values().toArray(new String[0]);
}
What you could do is something like this (rough code):
String[] myOccurences = test.split(" ");
Then:
HashMap<String,Integer> occurencesMap = new HashMap<String,Integer>()
for( String s : myOccurences ){
if( occurencesMap.get( s ) == null ){
occurencesMap.put(s, 1);
} else {
occurencesMap.put(s, occurencesMap.get(s)++ );
}
}
Edit: The actual sorting (again rough code and unchecked):
List<String> mapKeys = new ArrayList<String>(occurencesMap.keySet()); // Keys
List<Integer> mapValues = new ArrayList<Integer>(occurencesMap.values()); // Values
TreeSet<Integer> sortedSet = new TreeSet( mapValues ); // Sorted according to natural order
Integer[] sortedValuesArray = sortedSet.toArray();
HashMap<String,Integer> lhMap = new LinkedHashMap<String,Integer>(); // LinkedHashMaps conserve order
for (int i=0; i<size; i++){
lhMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])), sortedValuesArray[i]);
}
mapKeys = new ArrayList<String>(occurencesMap.keySet()); // Keys again, this time sorted
Collections.sort(mapKeys, Collections.reverseOrder()); // Reverse since original ascending
String[] occurencesSortedByDescendingArray = mapKeys.toArray();
Feel free to comment.
If you want to use Guava:
Lists.transform(
Ordering
.natural()
.onResultOf(new Function<Multiset.Entry<String>, Integer>() {
public Integer apply(Multiset.Entry<String> entry) {
return entry.getCount();
}
})
.reverse()
.sortedCopy(
ImmutableMultiset.copyOf( Splitter.onPattern("\\s+").split(test) ).entrySet()
),
new Function<Multiset.Entry<String>, String>() {
public String apply(Multiset.Entry<String> entry) {
return entry.getElement();
}
}
);
I am not sure if a method exists for this exact purpose.
However, you could use the String.split() method to split the single string into an array of strings. From there, you could locate unique strings (either by manually checking or adding them all to a set, which would check for duplicates). Track (and increment a counter unique to each unique String) each time you add an element and it is not part of the collection. Then create an array that is sorted based on this count.
A map would be ideal for holding the String/count, as it would maintain the set of unique Strings as keys, and the count for each String as the value.