Removing brackets from list of anagrams
Hello, i have been asked to create new question insted of asking again in the same thread.
public static void main(String[] args) throws IOException {
getAnagrams(new InputStreamReader(new URL("http://www.puzzlers.org/pub/wordlists/unixdict.txt").openStream(),
StandardCharsets.UTF_8)).forEach(items -> {
for (String item : items) {
System.out.print(item + " ");
}
System.out.println();
});
}
private static String canonicalize(String string) {
return Stream.of(string.split("")).sorted().collect(Collectors.joining());
}
public static List<Set<String>> getAnagrams(Reader rr) {
Map<String, Set<String>> mapa = (Map<String, Set<String>>) new BufferedReader(rr).lines()
.flatMap(Pattern.compile("\\W+")::splitAsStream)
.collect(Collectors.groupingBy(Main::canonicalize, Collectors.toSet()));
return mapa.values().stream().filter(lista -> lista.size() > 4).collect(Collectors.toList());
}
}
How do i sort my output like "evil levi live veil vile"? Cuz for now i have "veil evil vile levi live"
UPDATE
Last thing is to sort output alphabeticaly
For now = "evil levi live veil vile, abel able bale bela elba"
Needed = "abel able bale bela elba, evil levi live veil vile"
Here's the easiest way I can think of
return mapa.values().stream()
.filter(lista -> lista.size() > 4)
.map(set -> new TreeSet<>(set))
.collect(Collectors.toList());
TreeSet keeps its elements sorted.
Related
I am using a 2D LinkedHashSet for my program. I was wondering how I can iterate through the two dimensional HashSet and print its contents without doing this:
System.out.println(name of initialized HashSet)
Here is my code for initialization of the 2D LinkedHashSet:
LinkedHashSet<LinkedHashSet<String>> block = new LinkedHashSet<LinkedHashSet<String>>();
You can use 2 loops for this, similar to how you would for an array:
for (Set<String> innerSet : block) {
for (String string : innerSet) {
System.out.println(string);
}
}
You can also use streams to print each element:
block.stream()
.flatMap(Collection::stream)
.forEach(System.out::println);
If one wants to use a functional solution, one could use the following:
Ideone demo
import java.util.LinkedHashSet;
public class Streamify {
public static void main (final String... args) {
final LinkedHashSet<LinkedHashSet<String>> block = new LinkedHashSet<>();
final LinkedHashSet<String> lineOne = new LinkedHashSet<>();
lineOne.add("Hello");
lineOne.add("World");
block.add(lineOne);
final LinkedHashSet<String> lineTwo = new LinkedHashSet<>();
lineTwo.add("Hi");
lineTwo.add("Universe");
block.add(lineTwo);
block.forEach(line -> {
line.forEach(System.out::print);
System.out.println();
});
}
}
I got an array of elements like :
ArrayList<String> t = new ArrayList();
t.add("/folder1/sub-folder1");
t.add("/folder2/sub-folder2");
t.add("/folder1/sub-folder1/data");
I need to get output as /folder1/sub-folder1 which is mostly repeated path.
In python this can be achieved using the below function:
def getRepeatedPath(self, L):
""" Returns the highest repeated path/string in a provided list """
try:
pkgname = max(g(sorted(L)), key=lambda(x, v): (len(list(v)), -L.index(x)))[0]
return pkgname.replace("/", ".")
except:
return "UNKNOWN"
I am trying to work on equivalent lambda function in Java. I got struck and need some help in the lambda implementation.
public String mostRepeatedSubString(ArrayList<String> pathArray) {
Collections.sort(pathArray);
String mostRepeatedString = null;
Map<String,Integer> x = pathArray.stream.map(s->s.split("/")).collect(Collectors.toMap());
return mostRepeatedString;
}
Lots of tweaking, but I finally got it!
public static void main(String[] args) {
ArrayList<String> t = new ArrayList<String>();
t.add("folder1/sub-folder1");
t.add("folder2/sub-folder2");
t.add("folder1/sub-folder1/data");
System.out.println(mostRepeatedSubString(t));
}
public static String mostRepeatedSubString(List<String> pathArray) {
return pathArray
.stream()
// Split to lists of strings
.map(s -> Arrays.asList(s.split("/")))
// Group by first folder
.collect(Collectors.groupingBy(lst -> lst.get(0)))
// Find the key with the largest list value
.entrySet()
.stream()
.max((e1, e2) -> e1.getValue().size() - e2.getValue().size())
// Extract that largest list
.map(Entry::getValue)
.orElse(Arrays.asList())
// Intersect the lists in that list to find maximal matching
.stream()
.reduce(YourClassName::commonPrefix)
// Change back to a string
.map(lst -> String.join("/", lst))
.orElse("");
}
private static List<String> commonPrefix(List<String> lst1, List<String> lst2) {
int maxIndex = 0;
while(maxIndex < Math.min(lst1.size(), lst2.size())&& lst1.get(maxIndex).equals(lst2.get(maxIndex))) {
maxIndex++;
}
return lst1.subList(0, maxIndex);
}
Note that I had to remove the initial / from the paths, otherwise that character would have been used in the split, resulting in the first string in every path list being the empty string, which would always be the most common prefix. Shouldn't be too hard to do this in pre-processing though.
I have a list of Strings:
List<String> terms = ["Coding is great", "Search Engines are great", "Google is a nice search engine"]
How do I get the frequency of each word in the list:
E.g.{Coding:1, Search:2, Engines:1, engine:1, ....}
Here is my Code:
Map<String, Integer> wordFreqMap = new HashMap<>();
for (String contextTerm : term.getContexTerms() )
{
String[] wordsArr = contextTerm.split(" ");
for (String word : wordsArr)
{
Integer freq = wordFreqMap.get(word); //this line is getting reset every time I goto a new COntexTerm
freq = (freq == null) ? 1: ++freq;
wordFreqMap.put(word, freq);
}
}
An idiomatic solution with Java 8 streams:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class SplitWordCount
{
public static void main(String[] args)
{
List<String> terms = Arrays.asList(
"Coding is great",
"Search Engines are great",
"Google is a nice search engine");
Map<String, Integer> result = terms.parallelStream().
flatMap(s -> Arrays.asList(s.split(" ")).stream()).
collect(Collectors.toConcurrentMap(
w -> w.toLowerCase(), w -> 1, Integer::sum));
System.out.println(result);
}
}
Note that you may have to think about whether upper/lower case of the strings should play a role. This one onverts the strings to lower case, and uses them as the keys for the final map. The result is then:
{coding=1, a=1, search=2, are=1, engine=1, engines=1,
is=2, google=1, great=2, nice=1}
public static void main(String[] args) {
String msg="Coding is great search Engines are great Google is a nice search engine";
ArrayList<String> list2 = new ArrayList<>();
Map map = new HashMap();
list2.addAll((List)Arrays.asList(msg.split(" ")));
String n[]=msg.split(" ");
int f=0;
for(int i=0;i<n.length;i++){
f=Collections.frequency(list2, n[i]);
map.put(n[i],f);
}
System.out.println("values are "+map);
}
Because the answer with Java 8, while being good, does not show you how to parallel it in Java 7 (and beside default implementation is the same than stream), here is an example:
public static void main(final String[] args) throws InterruptedException {
final ExecutorService service = Executors.newFixedThreadPool(10);
final List<String> terms = Arrays.asList("Coding is great", "Search Engines are great",
"Google is a nice search engine");
final List<Callable<String[]>> callables = new ArrayList<>(terms.size());
for (final String term : terms) {
callables.add(new Callable<String[]>() {
#Override
public String[] call() throws Exception {
System.out.println("splitting word: " + term);
return term.split(" ");
}
});
}
final ConcurrentMap<String, AtomicInteger> counter = new ConcurrentHashMap<>();
final List<Callable<Void>> callables2 = new ArrayList<>(terms.size());
for (final Future<String[]> future : service.invokeAll(callables)) {
callables2.add(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("counting word");
// invokeAll implies that the future finished it work
for (String word : future.get()) {
String lc = word.toLowerCase();
// here it get tricky. Two thread might add the same word.
AtomicInteger actual = counter.get(lc);
if (null == actual) {
final AtomicInteger nv = new AtomicInteger();
actual = counter.putIfAbsent(lc, nv);
if (null == actual) {
actual = nv; // nv got added.
}
}
actual.incrementAndGet();
}
return null;
}
});
}
service.invokeAll(callables2);
service.shutdown();
System.out.println(counter);
}
Yes, Java 8 simplifies the work !
No, I tested it but don't know if it is better than simple loops nor if it perfectly threadsafe.
(And seeing how you define your list, are not coding in Groovy ? There exists parallelism support in Groovy).
Apologies for the newbie question, but what's the proper way to get a Set (say LinkedHashSet) in reverse order? For Collections there's Collections.reverse(Collection c), but how does one do it for a Set with ordered elements (like a LinkedHashSet)?
Sets are not ordered in general, so to preserve the sorting, after sorting the set as a list, you would need to use a known iteration order implementation of Set, such as LinkedHashSet
List list = new ArrayList(set);
Collections.sort(list, Collections.reverseOrder());
Set resultSet = new LinkedHashSet(list);
You could also use TreeSet with a comparator, but that is not as fast as the ArrayList method above.
public class LargestArray {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<>();
Set<Integer> set = new TreeSet<>();
set.add(10);
set.add(20);
set.add(7);
set.add(4);
set.add(1);
set.add(2);
set.add(3);
set.add(4);
System.out.println("after Sorting");
for(int i : set) {
System.out.print(" " + i);
}
al.addAll(set);
set.clear();
Collections.reverse(al);
System.out.println();
System.out.println("After Reverse");
for (int i : al) {
System.out.print(" " + i);
}
}
}
output = after Sorting
1 2 3 4 7 10 20
After Reverse
20 10 7 4 3 2 1
Check this out
http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html#descendingSet()
If you use a TreeSet you can get reverse order by calling descendingSet.
I will explain you with an example. Comments are added in mid of the code for better understanding.
public class ReverseLinkedHashSet {
public static void main(String[] args) {
// creating a LinkedHashSet object which is
// of type String or any. Will take a example of String.
HashSet<String> cars = new LinkedHashSet<String>();
// adding car elements to LinkedHashSet object as below
cars.add("Toyato");
cars.add("Hundai");
cars.add("Porshe");
cars.add("BMW");
// Iterating using enhanced for-loop to see the order.
System.out.println("Insertion Order: Iterating LinkedHashSet\n");
for(String car : cars) {
System.out.println(car);
// Output will be as below
//Toyato
//Hundai
//Porshe
//BMW
}
// Now convert to ArrayList to rearrange to reverse
// the linkedHashset
List<String> listOfCars = new ArrayList<String>(cars);
// to reverse LinkedHashSet contents
Collections.reverse(listOfCars);
// reverse order of LinkedHashSet contents
// can be done as below
System.out.println("\n\n\nReverse Order of LinkedHashSet\n");
for(String car : listOfCars) {
System.out.println(car);
// Output will be as below
//BMW
//Porshe
//Hundai
//Toyato
}
}
}
Also, I suggest not to use LinkedhashSet without a strong reason. For a complex application, it will reduce the performance. Use HashSet instead.
Java 8, I using solution below,
Set<String> setTest = new HashSet<>();
setTest.add("1");
setTest.add("2");
setTest.add("3");
List<String> list = new ArrayList<>(setTest);
list.sort(Collections.reverseOrder());
Set<String> result = new LinkedHashSet<>(list);
for (String item: result) {
System.out.println("---> " + item);
}
Result:
---> 3
---> 2
---> 1
Work for me.
I am having one problem in java arraylist. I am good in databases :) We normally use
"group by" to group rows. I want the same thing but in java for one of my project
I have following format in arraylist
name1:val1
name1:val2
name1:val3
name2:val8
name2:val7
name7:val54
name7:val76
name7:val34
I want to convert this arraylist to give me following output:
-name1
val1
val2
val3
-name2
val8
val7
-name7
.
.
.
val34
this is not a school assignment :). may be for some of Java Guru it looks like a small
thing to do.
I like to do that kind of thing with a map.
import java.util.*;
public class DoIt {
public static void main(String[] args) {
List l = new ArrayList<String>();
l.add("name1:val1");
l.add("name1:val2");
l.add("name1:val3");
l.add("name1:val4");
l.add("name2:val1");
Map results = new HashMap<String,String>();
for (Iterator i = l.iterator(); i.hasNext();) {
String s = (String)i.next();
String[] tmp = s.split(":");
if (!results.containsKey(tmp[0])) {
System.out.println("-"+tmp[0]+"\n"+tmp[1]);
results.put(tmp[0], tmp[1]);
} else {
System.out.println(tmp[1]);
}
}
}
}
Use a Map<String, List<Integer>>. You could use the following snippets:
// declare
Map<String, List<Integer>> m = new HashMap<String, List<Integer>>();
// insert into the structure the pair 'a':2
List<Integer> l = m.get("a");
if ( l == null ) {
l = new ArrayList<Integer>();
m.put("a", l);
}
l.add(2);
// iterate over the values
for (Map<String, List<Integer>>.Entry e : m) {
System.out.println("-" + e.getKey());
for (Integer i : m.getValue()) {
System.out.println(" " + i);
}
}
What you are looking for is called multi-map.
There is no standard multi-map in java.util, but Google collections has implemented it -> here. The project home page is here
Use Comparator
List<Samp> bla = new ArrayList<Samp>();
Collections.sort(bla, new Comparator<Samp>() {
#Override
public int compare(Samp s1, Samp s2) {
return s1.getCategory().compareTo(s2.getCategory());
}
});
then Create 1 List .,. compare if that list already contains the category, if not,
add Category and Name, else just add Name. see code below :)
List<String> catList = new ArrayList<String>();
for(Samp s : bla){
if (!catList.contains(s.getCategory())){
catList.add(s.getCategory());
System.out.println(s.getCategory() + " - ");
System.out.println(s.getName());
} else {
System.out.println(s.getName());
}
}