Dart - swap list item or pop item from list - list

Using Dart, what is a good way of iterating through a list of strings in search for a specific one, when string is found move it to the front of the list?
For example, if looking for the letter 'b'. Find it, move it up front.
['a', 'b', 'c']
=> ['b', 'a', 'c']
Not knowing Dart very well, I solved it with simple for-loop
List<String> example = ['a', 'b', 'c'];
for (int i = 0; i< example.length; i++) {
if (example[i] == 'b') {
final temp = example[0];
example[0] = example[i];
example[i] = temp;
}
}
Is there a way in dart to call some array method on a list to find a specific item, remove it from the original list and return the removed item? Like .splice() in JS.

for List delete and then insert to move it up to front
if(example.remove("b"))
example.insert(0, "b");

Properties of the List data structure
When approaching this problem it is helpful to know some properties of the list data structure:
Changing the value at an index is fast.
Adding or removing items from the end of a list is fast.
Removing items from the beginning or middle of a list is slow because all the items after it need to move up one index.
Adding an item to the beginning or middle of a list is slow because all the items after it need to move back one index.
Removing and inserting
Thus, although #FloW's answer is very concise and easy to read, it's slow because it requires both removing from the middle of a list and adding to the beginning of a list:
final example = ["a", "b", "c"];
if (example.remove("b")) {
example.insert(0, "b");
}
For short lists it probably doesn't matter but for long lists this could have noticeable performance impacts.
Swapping
Since the requirements in the original problem allow for swapping rather than removing and inserting, the for loop solution given in the question itself is better in my opinion:
List<String> example = ['a', 'b', 'c'];
for (int i = 0; i < example.length; i++) {
if (example[i] == 'b') {
final temp = example[0];
example[0] = example[i];
example[i] = temp;
}
}
Although this search still requires visiting every item in the list, it doesn't require moving everything if a match is found. Only the two affected indices are changed.
You could improve the efficiency even more by adding a break statement to the end of the if block, which would make it equivalent to using indexOf:
final example = ['a', 'b', 'c'];
final value = 'b';
final index = example.indexOf(value);
example[index] = example[0];
example[0] = value;

Related

Sort multiple sublists of list to create new list, Dart

I'm trying to sort an entire list according to one property. Afterwards I'd like to sort this list according to a second property, but in groups of 4. So, after sorting the list once, I want to look at the first 4 positions and sort only these 4 according to the second property - then move on to the next 4 positions and sort these again, and so on...
This is what I have so far:
class myElements {
int Position;
String text;
int Top;
int Left;
myElements(int Position, String text, int Top, int Left){
this.Position = Position;
this.text = text;
this.Top = Top;
this.Left = Left;
}
}
var FirstList = new List<myElements>();
var newList = new List<myElements>();
Adding Elements to my first list:
myElements Test = myElements(ElementNumber, text, Top, Left);
FirstList.add(Test);
Then sorting for the first time according to 'Top':
Comparator<myElements> TextComparator = (a, b) => a.Top.compareTo(b.Top);
FirstList.sort(TextComparator);
Here is where I'm stuck. I'm trying to sort the list again, but only in groups of 4 - this time according to 'Left':
for (int i = 0; i < FirstList.length; i += 4) {
Comparator<myElements> TextComparator2 = (a, b) =>
a.Left.compareTo(b.Left);
newList.addAll(FirstList.sublist(i, i + 3).sort(TextComparator2)); //this line does not work
}
I think I am stuck trying to access my sorted sublist: (FirstList.sublist(i, i + 4).sort(TextComparator2) . If I could add these to a new list, it should work.
However any other suggestions are more than welcome.
Thanks so much!
newList.addAll(FirstList.sublist(i, i + 3).sort(TextComparator2)); //this line does not work
Your code is almost correct. You have the right idea, but you ended up trying to do too much in one line of code.
Breaking it down a bit, your code is equivalent to:
var sublist = FirstList.sublist(i, i + 3);
newList.addAll(sublist.sort(...)); // Does not work
And that doesn't work because List.sort does not return a value. It mutates the list instead of returning a new list.
It would work if you instead did:
var sublist = FirstList.sublist(i, i + 3);
sublist.sort();
newList.addAll(sublist);
Also, List.sublist uses an exclusive end index. If you want to create sublists with 4 elements, you would need to use sublist(i, i + 4).

Simulation in python for Unique matches of demand supply using lists

I have data in the form of list of lists where I am trying to match the demand and supply such that each demand matches uniquely to one supply item.
dmndId_w_freq = [['a',4,[1,2,3,4]],['b',6,[5,6,7,8,3,4]],['c',7,[6,5,7,9,8,3,4]],['d',8,[1,6,3,4,5,6,7,10]]]
num_sims = 1
for sim_count in range(num_sims):
dmndID_used_flag = {}
splID_used_flag = {}
dmndID_splId_one_match = {}
for i in dmndId_w_freq:
if i[0] not in dmndID_used_flag.keys():
for j in i[2]:
#print j
#print "CLICK TO CONTINUE..."
#raw_input()
if j in splID_used_flag.keys():
i[2].remove(j)
dmndID_splId_one_match[i[0]] = i[2][0]
splID_used_flag[i[2][0]] = 1
dmndID_used_flag[i[0]] = 1
print
print dmndID_splId_one_match
#print splID_used_flag
#print dmndID_used_flag
#raw_input()
I would expect the output dmndID_splId_one_match to be something like {'a':1,'b':5,'c':6,'d':3}.
But I end up getting {'a':1,'b':5,'c':6,'d':6}
So I am NOT getting a unique match as the supply item 6 is getting mapped to demands 'c' as well as demand 'd'.
I tried to debug the code by looping through it and it seems that the problem is in the for-loop
for j in i[2]:
The code is not going through all the elements of i[2]. It does not happen with the 'a' and 'b' part. but starts happening with the 'c' part. It goes over 6 and 5 but skips 7 (the third element of the list [6,5,7,9,8,3,4]). Similarly, in the 'd' part it skips the 2nd element 6 in the list [1,6,3,4,5,6,7,10]. And that is why the mapping is happening twice, since I am not able to remove it.
What am I doing wrong that it is not executing the for-loop as expected?
Is there a better way to write this code?
I figured out the problem in the for loop. I am looping through i[2] and then trying to modify it within the loop. this makes it unstable.

Python: referring to each duplicate item in a list by unique index

I am trying to extract particular lines from txt output file. The lines I am interested in are few lines above and few below the key_string that I am using to search through the results. The key string is the same for each results.
fi = open('Inputfile.txt')
fo = open('Outputfile.txt', 'a')
lines = fi.readlines()
filtered_list=[]
for item in lines:
if item.startswith("key string"):
filtered_list.append(lines[lines.index(item)-2])
filtered_list.append(lines[lines.index(item)+6])
filtered_list.append(lines[lines.index(item)+10])
filtered_list.append(lines[lines.index(item)+11])
fo.writelines(filtered_list)
fi.close()
fo.close()
The output file contains the right lines for the first record, but multiplied for every record available. How can I update the indexing so it can read every individual record? I've tried to find the solution but as a novice programmer I was struggling to use enumerate() function or collections package.
First of all, it would probably help if you said what exactly goes wrong with your code (a stack trace, it doesn't work at all, etc). Anyway, here's some thoughts. You can try to divide your problem into subproblems to make it easier to work with. In this case, let's separate finding the relevant lines from collecting them.
First, let's find the indexes of all the relevant lines.
key = "key string"
relevant = []
for i, item in enumerate(lines):
if item.startswith(key):
relevant.append(item)
enumerate is actually quite simple. It takes a list, and returns a sequence of (index, item) pairs. So, enumerate(['a', 'b', 'c']) returns [(0, 'a'), (1, 'b'), (2, 'c')].
What I had written above can be achieved with a list comprehension:
relevant = [i for (i, item) in enumerate(lines) if item.startswith(key)]
So, we have the indexes of the relevant lines. Now, let's collected them. You are interested in the line 2 lines before it and 6 and 10 and 11 lines after it. If your first lines contains the key, then you have a problem – you don't really want lines[-1] – that's the last item! Also, you need to handle the situation in which your offset would take you past the end of the list: otherwise Python will raise an IndexError.
out = []
for r in relevant:
for offset in -2, 6, 10, 11:
index = r + offset
if 0 < index < len(lines):
out.append(lines[index])
You could also catch the IndexError, but that won't save us much typing, as we have to handle negative indexes anyway.
The whole program would look like this:
key = "key string"
with open('Inputfile.txt') as fi:
lines = fi.readlines()
relevant = [i for (i, item) in enumerate(lines) if item.startswith(key)]
out = []
for r in relevant:
for offset in -2, 6, 10, 11:
index = r + offset
if 0 < index < len(lines):
out.append(lines[index])
with open('Outputfile.txt', 'a') as fi:
fi.writelines(out)
To get rid of duplicates you can cast list to set; example:
x=['a','b','a']
y=set(x)
print(y)
will result in:
['a','b']

removing cyclic substrings from python list

I have a Python list like the following:
['IKW', 'IQW', 'IWK', 'IWQ', 'KIW', 'KLW', 'KWI', 'KWL', 'LKW', 'LQW', 'LWK', 'LWQ', 'QIW', 'QLW', 'QWI', 'QWL', 'WIK', 'WIQ', 'WKI', 'WKL', 'WLK', 'WLQ', 'WQI', 'WQL']
If we pick, say the second element IQW, we see that the list has duplicates of this item HOWEVER its not noticeable right away. This is because it is cyclic. I mean the following are equivalent.
IQW, QWI, WIQ
Also it could be backwards which is also a duplicate so I want it removed. So now the list of duplicates are (the reverse of each of one these)
IQW, QWI, WIQ , WQI, IWQ, QIW
So essentially I would like IQW to be the only one left.
Bonus points, if the one that is remaining in the list is sorted alphabetically.
The way I did was to sort the entire list by alphabetical order:
`IQW`, `QWI`, `WIQ` , `WQI`, `IWQ`, `QIW` ->
`IQW`, `IQW`, `IQW`, `IQW`, `IQW` `IQW`
and then remove the duplicates.
However this also removes combinations say i have ABCD and CDAB. These are not the same because the ends only meet once. But my method will sort them to ABCD and ABCD and remove one.
My code:
print cur_list
sortedlist = list()
for i in range(len(cur_list)):
sortedlist.append(''.join(map(str, sorted(cur_list[i]))))
sortedlist = set(sortedlist)
L = ['IKW', 'IQW', 'IWK', 'IWQ', 'KIW', 'KLW', 'KWI', 'KWL', 'LKW', 'LQW', 'LWK', 'LWQ', 'QIW', 'QLW', 'QWI', 'QWL', 'WIK', 'WIQ', 'WKI', 'WKL', 'WLK', 'WLQ', 'WQI', 'WQL']
seen = set()
res = []
for item in L:
c = item.index(min(item))
item = item[c:] + item[:c]
if item not in seen:
seen.add(item)
seen.add(item[0]+item[-1:0:-1])
res.append(item)
print res
output:
['IKW', 'IQW', 'KLW', 'LQW']
Here is the solution I coded: If anyone has a better algo, I will accept that as answer:
mylist = list()
for item in copy_of_cur:
linear_peptide = item+item
mylist = filter(lambda x: len(x) == 3 , subpeptides_linear(linear_peptide))
for subitem in mylist:
if subitem != item:
if subitem in cur_list:
cur_list.remove(subitem)

List.shuffle() in Dart?

I'm looking every where on the web (dart website, stackoverflow, forums, etc), and I can't find my answer.
So there is my problem: I need to write a function, that print a random sort of a list, witch is provided as an argument. : In dart as well.
I try with maps, with Sets, with list ... I try the method with assert, with sort, I look at random method with Math on dart librabry ... nothing can do what I wana do.
Can some one help me with this?
Here some draft:
var element03 = query('#exercice03');
var uneliste03 = {'01':'Jean', '02':'Maximilien', '03':'Brigitte', '04':'Sonia', '05':'Jean-Pierre', '06':'Sandra'};
var alluneliste03 = new Map.from(uneliste03);
assert(uneliste03 != alluneliste03);
print(alluneliste03);
var ingredients = new Set();
ingredients.addAll(['Jean', 'Maximilien', 'Brigitte', 'Sonia', 'Jean-Pierre', 'Sandra']);
var alluneliste03 = new Map.from(ingredients);
assert(ingredients != alluneliste03);
//assert(ingredients.length == 4);
print(ingredients);
var fruits = <String>['bananas', 'apples', 'oranges'];
fruits.sort();
print(fruits);
There is a shuffle method in the List class. The methods shuffles the list in place. You can call it without an argument or provide a random number generator instance:
var list = ['a', 'b', 'c', 'd'];
list.shuffle();
print('$list');
The collection package comes with a shuffle function/extension that also supports specifying a sub range to shuffle:
void shuffle (
List list,
[int start = 0,
int end]
)
Here is a basic shuffle function. Note that the resulting shuffle is not cryptographically strong. It uses Dart's Random class, which produces pseudorandom data not suitable for cryptographic use.
import 'dart:math';
List shuffle(List items) {
var random = new Random();
// Go through all elements.
for (var i = items.length - 1; i > 0; i--) {
// Pick a pseudorandom number according to the list length
var n = random.nextInt(i + 1);
var temp = items[i];
items[i] = items[n];
items[n] = temp;
}
return items;
}
main() {
var items = ['foo', 'bar', 'baz', 'qux'];
print(shuffle(items));
}
You can use shuffle() with 2 dots like Vinoth Vino said.
List cities = ["Ankara","London","Paris"];
List mixed = cities..shuffle();
print(mixed);
// [London, Paris, Ankara]