I have an arraylist that contains urls in the form similar to :
stackoverflow.com/questions/ask/hello
stackoverflow.com/questions/ask
stackoverflow.com/questions
stackoverflow.com/
If I only wanted to keep the first one and remove the rest, how would I go about doing that since technically they are not duplicates.
I thought of using substring manipulation but not to sure how to implement that.any ideas appreciated.
Assuming I understand the question correctly, you can accomplish this by looping through your ArrayList, building a list of found domains, and simultaneously outputting a new list only when the found domain is not already a member of that first list.
Or, you could build a dictionary of domain to url by iterating through the ArrayList in reverse. Since a dictionary can only have one value per key, the URLs will overwrite themselves in the dictionary and you will only have one URL per domain. Since you iterated in reverse, you will be left with a dictionary containing the first match in the ArrayList. You could then use LINQ to grab just the values (e.g. MyDictionary.Select(elem => elem.Value)).
An example implementation of the second way I mentioned (in C#, you can convert it) is:
Dictionary<string, string> MyDictionary = new Dictionary<string, string>();
foreach(string Url in MyArrayList.Reverse())
MyDictionary[Url.Split("/")[0]] = Url;
There are dozens of ways you could accomplish this task. These are just two examples.
Related
I have a list of Longs in Kotlin and I want to make them strings for UI purposes with maybe some prefix or altered in some way. For example, adding "$" in the front or the word "dollars" at the end.
I know I can simply iterate over them all like:
val myNewStrings = ArrayList<String>()
longValues.forEach { myNewStrings.add("$it dollars") }
I guess I'm just getting nitpicky, but I feel like there is a way to inline this or change the original long list without creating a new string list?
EDIT/UPDATE: Sorry for the initial confusion of my terms. I meant writing the code in one line and not inlining a function. I knew it was possible, but couldn't remember kotlin's map function feature at the time of writing. Thank you all for the useful information though. I learned a lot, thanks.
You are looking for a map, a map takes a lambda, and creates a list based on the result of the lambda
val myNewStrings = longValues.map { "$it dollars" }
map is an extension that has 2 generic types, the first is for knowing what type is iterating and the second what type is going to return. The lambda we pass as argument is actually transform: (T) -> R so you can see it has to be a function that receives a T which is the source type and then returns an R which is the lambda result. Lambdas doesn't need to specify return because the last line is the return by default.
You can use the map-function on List. It creates a new list where every element has been applied a function.
Like this:
val myNewStrings = longValues.map { "$it dollars" }
In Kotlin inline is a keyword that refers to the compiler substituting a function call with the contents of the function directly. I don't think that's what you're asking about here. Maybe you meant you want to write the code on one line.
You might want to read over the Collections documentation, specifically the Mapping section.
The mapping transformation creates a collection from the results of a
function on the elements of another collection. The basic mapping
function is
map().
It applies the given lambda function to each subsequent element and
returns the list of the lambda results. The order of results is the
same as the original order of elements.
val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 })
For your example, this would look as the others said:
val myNewStrings = longValues.map { "$it dollars" }
I feel like there is a way to inline this or change the original long list without creating a new string list?
No. You have Longs, and you want Strings. The only way is to create new Strings. You could avoid creating a new List by changing the type of the original list from List<Long> to List<Any> and editing it in place, but that would be overkill and make the code overly complex, harder to follow, and more error-prone.
Like people have said, unless there's a performance issue here (like a billion strings where you're only using a handful) just creating the list you want is probably the way to go. You have a few options though!
Sequences are lazily evaluated, when there's a long chain of operations they complete the chain on each item in turn, instead of creating an intermediate full list for every operation in the chain. So that can mean less memory use, and more efficiency if you only need certain items, or you want to stop early. They have overhead though so you need to be sure it's worth it, and for your use-case (turning a list into another list) there are no intermediate lists to avoid, and I'm guessing you're using the whole thing. Probably better to just make the String list, once, and then use it?
Your other option is to make a function that takes a Long and makes a String - whatever function you're passing to map, basically, except use it when you need it. If you have a very large number of Longs and you really don't want every possible String version in memory, just generate them whenever you display them. You could make it an extension function or property if you like, so you can just go
fun Long.display() = "$this dollars"
val Long.dollaridoos: String get() = "$this.dollars"
print(number.display())
print(number.dollaridoos)
or make a wrapper object holding your list and giving access to a stringified version of the values. Whatever's your jam
Also the map approach is more efficient than creating an ArrayList and adding to it, because it can allocate a list with the correct capacity from the get-go - arbitrarily adding to an unsized list will keep growing it when it gets too big, then it has to copy to another (larger) array... until that one fills up, then it happens again...
Using Roslyn for VB.Net I can get the Type of an Expression using the code below.
Dim ExpressionType As TypeInfo = SemanticModel.GetTypeInfo(ForEachStatement.Expression)
If the expression is a collection (List, Dictionary, Array, Collection...) how can I find out what is in the collection? For the example below I want to find DocumentIdAndRoot
Dim docs As List(Of DocumentIdAndRoot) = Await RemoveParameterAsync(document, parameter, root, cancellationToken)
If your question is specific to foreach, then you should use SemanticModel.GetForEachStatementInfo(), which returns a ForEachStatementInfo with all the necessary information.
What you could do is take the TypeInfo you get, and look at the ImplementedInterfaces property. One of those would be IEnumerable or ICollection, and from there you could look at what the generic parameter is.
If you do have a ForEach involved somewhere, you're still better off using Tamas' approach, since that will correctly implement the language rules there.
I wanted a collection that would contain a bunch of unique strings. Hashset seemed to be the best option since it removes duplicates and is quick about it.
However how would i go about finding an item in the hash set? I could just loop through all the elements but wouldn't that defeat the purpose of being a hashset? Essentially i just want a dictionary where the key is the value.
Hashsets are not used for searching. They are used to treat collection as a whole. You can use it as for what mathematical sets are used for: to create unions, intersections, or for checks of duplication etc.
The dictionaries and hashsets are similar in internal implementation, since they are based on hashtables. But sets do not have keys, since they are not allowed for the lookup of the elements. You must use dictionary for it. If you want to ask a set for an element, you will have to enumerate thru them all.
In the same way, you should not use Queues, stacks or linked list for looking for an element.
To have only strings in a dictionary you can use it like:
IDictionary<string, string dictionary =
new Dictionary<string, string>();
dictionary.Add("Foo", "Foo");
dictionary.Add("Bar", "Bar");
string stringThatILookFor = null;
if (dictionary.TryGetValue("Bar", out stringThatILookFor))
{
// Use stringThatILookFor, which has a value Bar
}
You need to be using Contains.
Dim hsStrings As HashSet(Of String) = {"a", "b", "c"}
If hsStrings.Contains("a") Then 'do smth
This question is probably pretty obvious to any person who knows how to use Bukkit properly, and I'm sorry if I missed a solution in the others, but this is really kicking my ass and I don't know what else to do, the tutorials have been utterly useless. There are really 2 things that I need help doing:
I need to learn how to create an indefinite number of instances of an object. I figure it'd be like this:
int num = 0;
public void create(){
String name = chocolate + num;
Thingy name = new Thingy();
}
So you see what I'm saying? I need to basically change the name that is given to each new instance so that it doesn't overwrite the last one when created. I swear I've looked everywhere, I've asked my Java professor and I can't get any answers.
2: I need to learn how to use the stupid scheduler, and I can't understand anything so far. Basically, when an event is detected, 2 things are called: one method which activates instantly, and one which needs to be given a 5 second delay, then called. The code is like this:
public onEvent(event e){
Thingy thing = new Thingy();
thing.method1();
thing.doOnDelay(method2(), 100 ticks);
}
Once again, I apologize if I am not giving too many specifics, but I cannot FOR THE LIFE OF ME find anything about the Bukkit event scheduler that I can understand.
DO NOT leave me links to the Bukkit official tutorials, I cannot understand them at all and it'll be a waste of an answer. I need somebody who can help me, I am a starting plugin writer.
I've had Programming I and II with focus in Java, so many basic things I know, I just need Bukkit-specific help for the second one.
The first one has had me confused since I started programming.
Ok, so for the first question I think you want to use a data structure. Depending on what you're doing, there are different data structures to use. A data structure is simply a container that you can use to store many instances of a type of object. The data structures that are available to you are:
HashMap
HashSet
TreeMap
List
ArrayList
Vector
There are more, but these are the big ones. HashMap, HashSet, and TreeMap are all part of the Map class, which is notable for it's speedy operations. To use the hashmap, you instantiate it with HashMap<KeyThing, ValueThingy> thing = new HashMap<KeyThing, ValueThing>(); then you add elements to it with thing.put(key, value). Thn when you want to get a value out of it, you just use thing.get(key) HashMaps use an algorithm that's super fast to get the values, but a consequence of this is that the HashMap doesn't store it's entries in any particular order. Therefore when you want to loop though it with a for loop, it randomly returns it's entries (Not truly random because memory and stuff). Also, it's important to note that you can only have one of each individual key. If you try to put in a key that already exists in the map, it will over-right the value for that key.
The HashSet is like a HashMap but without storing values to go with it. It's a pretty good container if all you need to use it for is to determine if an object is inside it.
The TreeMap is one of the only maps that store it's values in a particular order. You have to provide a Comparator (something that tells if an object is less than another object) so that it knows the order to put the values if it wants them to be in ascending order.
List and ArrayList are not maps. Their elements are put in with a index address. With the List, you have to specify the number of elements you're going to be putting into it. Lists do not change size. ArrayLists are like lists in that each element can be retrieved with arrayListThing.get(index) but the ArrayList can change size. You add elements to an ArrayList by arrayListThing.add(Thing).
The Vector is a lot like an ArrayList. It actually functions about the same and I'm not quite sure what the difference between them is.
At any rate, you can use these data structures to store a lot of objects by making a loop. Here's an example with a Vector.
Vector<Thing> thing = new Vector<Thing>();
int numberofthings = 100;
for(int i = 0; i < numberofthings; i++) {
thing.add(new Thing());
}
That will give you a vector full of things which you can then iterate through with
for(Thing elem:thing) {
thing.dostuff
}
Ok, now for the second problem. You are correct that you need to use the Bukkit Scheduler. Here is how:
Make a class that extends BukkitRunnable
public class RunnableThing extends BukkitRunnable {
public void run() {
//what you want to do. You have to make this method.
}
}
Then what you want to do when you want to execute that thing is you make a new BukkitTask object using your RunnableThing
BukkitTask example = new RunnableThing().runTaskLater(plugin, ticks)
You have to do some math to figure out how many ticks you want. 20 ticks = 1 second. Other than that I think that covers all your questions.
Hi is there a standard place for accessing empty array constants in the JDK > 1.5.
When I want to do a conversion from a String Collection (e.g. ArrayList)to a String Array I find myself using my own
which is defined in my own Constants class:
public static final String[] EMPTY_STRING_ARRAY = new String[0];
And then in my client code something like:
String[] retVal = myStringList.toArray(Constants.EMPTY_STRING_ARRAY);
return retVal;
I was wondering if this is the "idiomatic" way of doing it or if I'm missing something
I get the impression from the brief search I did that this kind of thing is prevalent in many people's code.
Any ideas, answers, comment (aside from that I shouldn't really use String Arrays) greatly appreciated,
Cheers
Simon
I would recommend the following code improvement :
String[] retval = myStringList.toArray(new String[myStringList.size()]);
This way, the toArray method uses the provided, appropriately-sized array as a container, instead of creating a new one behind the scenes. From the ArrayList javadoc :
If the list fits in the specified
array, it is returned therein.
Otherwise, a new array is allocated
with the runtime type of the specified
array and the size of this list.
There are no array definitions like that in the JDK anywhere. The only two standard ways of doing it in the JDK are that which you list or
String ret[] = new String[myStringList.size()];
myStringList.toArray(ret);
return ret;