I ran over many questions in stackoverflow but none seemed to help me. I know there are many like this post, but I'm in need of help.
I'm trying to get a table's column into array and then I'm trying to remove duplicate elements. This jsfiddle illustrates the situation. Here's the code:
//sorry for the language
var days2 = ["Pazartesi", "Salı", "Pazartesi", "Çarşamba"];
var days = jQuery.makeArray($(".dersprg tr td:nth-child(6)"));
//the function works just fine on days2 array, but not on days array
function eliminateRepeat(array){
var i, j;
for(i=0 ; i<array.length ; i++){
for(j=i+1 ; j < array.length ; j++){
if(array[i] == array[j])
array.splice(j,1);
}
}
}
eliminateRepeat(days);
$(days).clone().appendTo(document.getElementById("test"));
The table I used is sort of huge for here, you'd better see it from jsfiddle.
Note: I used many functions written as answers to other questions, none seemed to work for me. I wrote my own function finally, which works fine on a string based array, however it still can not make the job done with a selected html element based array.
the function works just fine on days2 array, but not on days array
Yes, since there are no duplicates in the elements list. There may be some with the same text, but they are different nodes and do not equal with the == operator. You would need to change
if(array[i] == array[j])
to
if($(array[i]).text() == $(array[j]).text())
Btw, your splice removes one element from the array so that all indizes change. Yet, by going to the next index you are going to jump over one item. Use array.splice(j--,1);
Related
This is my first question here, I think the answer will be a small piece of Code.
Lets say i have a filled array at any lenght with unique elements:
let a = [A,B,C]
My question is,
How can I process the array, so that I have a list or x arrays , that show every possible order for these elements of the array above
like:
A,B,C
A,C,B
B,A,C
B,C,A
C,B,A
C,A,B
I dont really have an idea and tried to look in the web so far.
Thanks for the answers!
The recursive idea is:
function order(list, ans){
let size = list.length;
if(size == 0){
console.log(ans);
return;
}
for(var i = 0; i < size; i++){
let first = list.shift();
order(list, ans + `${first},`);
list.push(first);
}
}
Basically, for each element, you set it as a first and recursively do the same thing with the rest of the list.
Apology:
I apologize if this is a really basic question, I've looked around but since I never did get a very solid grounding in Javascript objects, I may be looking for answers in all the wrong places. That, and I don't have a solid enough grasp of Javascript to seperate out what is Javascript in all of the JQuery questions, and I don't want to use JQuery until I have a better understanding of Javascript in general. Thank you.
Problem:
I have a for loop that is going through an array of Google Map markers, to return them to active on the map I have open. The markers still exist somehow in the array because they return randomly when I iterate a couple times through this block of code. It will make it through one or two iterations of the loop, and then end. I added the hasOwnProperty test once I noticed the error, but this isn't skipping past the problem item in the array like I thought it should.
Question:
Why is my for loop skipping over objects in the array that I know are there?
//Code Loop
for (var i in removedMarkerArray)
{
//test for valid object
if (!removedMarkerArray[i].hasOwnProperty('title')) continue;
else alert("You dawg, this stuff passed.");
//the actual code doing real work, rather than testing.
if (removedMarkerArray[i].PD == PD)
{
removedMarkerArray[i].setMap(map);
placedMarkerArray.push(removedMarkerArray[i]);
removedMarkerArray.splice(i, 1);
}
}
//Example object in the array.
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: location.mouseover,
PD: location.PD
});
Thank you for reading through my question, and I'm looking forward to any answers.
for...in is meant to iterate over the Properties of an Object. Use a regular for loop if its meant to iterate through the indicies of an array.
This answer explains why: https://stackoverflow.com/a/5263872/1385467
If removedMarkerArray is a true Array you should use a classic for loop rather than for in. So you should be doing something of the sort:
for(var i = 0, n = removedMarkerArray.length; i < n; i++){
console.log(removedMarkerArray[i]); //check desired object in console for debugging
..code here
}
I like forEach for better readability as long as you are using a real Array.
removedMarkerArray.forEach(function(removedMarker, index) {
//test for valid object
if (!removedMarker.hasOwnProperty('title')) continue;
else console.log("You dawg, this stuff passed.");
//the actual code doing real work, rather than testing.
if (removedMarker.PD == PD)
{
removedMarker.setMap(map);
removedMarkerArray.splice(index, 1);
placedMarkerArray.push(removedMarker);
}
});
The problem with my code removing a marker from the map stems not from the fact that I used for...in instead of a true for loop, which the highest rated question stated, it stemmed from that I was skipping over items in my array. When I was originally writing this, I assumed for...in would protect me from that, but as far as this is concerned, it worked just like the loop below.
I added a decrement on the i variable, so that it would run through the same index again instead of skipping one. This is now touching on all of the markers in my arrays.
for (var i = 0; i < placedMarkerArray.length; i++)
{
if (placedMarkerArray[i].PD === PD)
{
placedMarkerArray[i].setMap(null);
console.log(placedMarkerArray[i]);
removedMarkerArray.push(placedMarkerArray[i]);
placedMarkerArray.splice(i, 1);
>> i--;
}
}
Was hoping someone may be able to point me in the right direction with this.
I have returned a list object in JSON format from .Net and then parse with JQuery.
var jsonOpens = $g.parseJSON(seriesReturn);
If I alert this I then receive the following:
1326531600000,8,49,1326531600000,8,49,1326535200000,11,169,1326535200000,11,169
What I then need to do with this is remove the second column.
I managed to do that by looping through and deleting
for (var i = 0; i < jsonOpens.length; i++) {
delete jsonOpens[i] [1];
}
This works but still leaves the column in place i.e alerts:
1326531600000,,49,1326531600000,,49,1326535200000,,169,1326535200000,,169
I tried doing a replace by replacing the double commas with single commas but this doesn't work in this format.
What would be the best way for me to identify a column and remove it completey whilst keeping the same format?
Assuming it's a JS array, you should be able to use the .splice() method to remove the appropriate elements:
http://www.w3schools.com/jsref/jsref_splice.asp
So, your loop would be (I think)
for (var i = 0; i < jsonOpens.length; i++) {
jsonOpens[i].splice(1,1);
}
Links to live examples # jsfiddle & jsbin.
So this function:
function symbolize(e){
var elements = e.childNodes; // text nodes are necessary!
console.log(elements);
for(var i=0; i < elements.length; i++){
t = elements[i];
var range = document.createRange(), offset = 0, length = t.nodeValue.length;
while(offset < length){
range.setStart(t, offset); range.setEnd(t, offset + 1);
range.surroundContents(document.createElement('symbol'));
offset++;
}
}
}
..should iterate over every letter and wrap it in a <symbol/> element. But it doesn't seem to be working.
So I added the console.log(); right after the *.childNodes have been fetched, but as you'll see in the example site above, the log contains 2 unexpected elements in front(!) of the array. And yeah, because of this, I have a feeling that surroundContents(); make the changes live(!). couldn't find any reference on this though
One of the elements is an empty Text node, the other is my <symbol/>. But yeah, this is totally unexpected result and messes up the rest of the function.
What could be wrong with it?
Thanks in advance!
Update
Oh, looks like the elements are added on Chrome, Firefox doesn't add the elements, but still halts the function.
Element.childNodes is indeed a live list , it could not be otherwise (that would mean an incorrect list of nodes). The easiest solution is to freeze (make a copy of) it before you mess with it (by surrounding existing ranges).
var elements = Array.prototype.slice.call(e.childNodes, 0);
https://developer.mozilla.org/en/childNodes it's of type NodeList
https://developer.mozilla.org/En/DOM/NodeList those are live lists
How do I remove an items from a data bound array? My code follows.
for(var i = 0; i < listBox.selectedIndices.length; i++) {
var toRemove = listFiles.selectedIndices[i];
dataArray.splice(toRemove, 1);
}
Thanks in advance!
Edit Here is my swf. The Add Photos works except when you remove items.
http://www.3rdshooter.com/Content/Flash/PhotoUploader.html
Add 3 photos different.
Remove 2nd photo.
Add a different photo.
SWF adds the 2nd photo to the end.
Any ideas on why it would be doing this?
Edit 2 Here is my code
private function OnSelectFileRefList(e:Event):void
{
Alert.show('addstart:' + arrayQueue.length);
for each (var f:FileReference in fileRefList.fileList)
{
var lid:ListItemData = new ListItemData();
lid.fileRef = f;
arrayQueue[arrayQueue.length]=lid;
}
Alert.show('addcomplete:' + arrayQueue.length);
listFiles.executeBindings();
Alert.show(ListItemData(arrayQueue[arrayQueue.length-1]).fileRef.name);
PushStatus('Added ' + fileRefList.fileList.length.toString() + ' photo(s) to queue!');
fileRefList.fileList.length = 0;
buttonUpload.enabled = (arrayQueue.length > 0);
}
private function OnButtonRemoveClicked(e:Event):void
{
for(var i:Number = 0; i < listFiles.selectedIndices.length; i++) {
var toRemove:Number = listFiles.selectedIndices[i];
//Alert.show(toRemove.toString());
arrayQueue.splice(toRemove, 1);
}
listFiles.executeBindings();
Alert.show('removecomplete:' + arrayQueue.length);
PushStatus('Removed photos from queue.');
buttonRemove.enabled = (listFiles.selectedItems.length > 0);
buttonUpload.enabled = (arrayQueue.length > 0);
}
It would definitely be helpful to know two things:
Which version of ActionScript are you targeting?
Judging from the behavior of your application, the error isn't occurring when the user removes an item from the list of files to upload. Looks more like an issue with your logic when a user adds a new item to the list. Any chance you could post that code as well?
UPDATE:
Instead of: arrayQueue[arrayQueue.length]=lid
Try: arrayQueue.push(lid)
That will add a new item to the end of the array and push the item in to that spot.
UPDATE 2:
Ok, did a little more digging. Turns out that the fileList doesn't get cleared every time the dialog is opened (if you're not creating a new instance of the FileReferenceList each time the user selects new files). You need to call splice() on the fileList after you add each file to your Array.
Try something like this in your AddFile() method...
for(var j:int=0; j < fileRefList.fileList.length; j++)
{
arrayQueue.push(fileRefList.fileList[j]);
fileRefList.fileList.splice(j, 1);
}
That will keep the fileList up to date rather than holding on to previous selections.
I see one issue. The selected indices are no longer valid once you have spliced out the first element from the array. But that should only be a problem when removing multiple items at once.
I think we need to see more code about how you are handling the upload before we can figure out what is going on. It looks to me like you are holding a reference to the removed FileReference or something. The described problem is occurring when you upload a new file, not when you remove the selected one.
Do you mean to use listBox and listFiles to refer to the same thing?
I'm stepping out on a limb here, because I don't have a ton of experience with JavaScript, but I'd do this the same way that I'd do it in C, C++, or Java: By copying the remaining array elements down into their new locations.
Assuming that listFiles.selectedIndices is sorted (and its contents are valid indices for dataArray), the code would be something like the following:
(WARNING: untested code follows.)
// Don't bother copying any elements below the first selected element.
var writeIndex = listFiles.selectedIndices[0];
var readIndex = listFiles.selectedIndices[0] + 1;
var selectionIndex = 1;
while(writeIndex < (dataArray.length - listFiles.selectedIndices.length)) {
if (selectionIndex < listFiles.selectedIndices.length) {
// If the read pointer is currently at a selected element,
// then bump it up until it's past selected range.
while(selectionIndex < listFiles.selectedIndices.length &&
readIndex == listFiles.selectedIndices[selectionIndex]) {
selectionIndex++;
readIndex++;
}
}
dataArray[writeIndex++] = dataArray[readIndex++];
}
// Remove the tail of the dataArray
if (writeIndex < dataArray.length) {
dataArray.splice(writeIndex, dataArray.length - writeIndex);
}
EDIT 2009/04/04: Your Remove algorithm still suffers from the flaw that as you remove items in listFiles.selectedIndices, you break the correspondence between the indices in arrayQueue and those in listFiles.selectedIndices.
To see this, try adding 3 files, then doing "Select All" and then hit Remove. It will start by removing the 1st file in the list (index 0). Now what had been the 2nd and 3rd files in the list are at indices 0 and 1. The next value taken from listFiles.selectedIndices is 1 -- but now, what had been the 3rd file is at index 1. So the former File #3 gets spliced out of the array, leaving the former 2nd file un-removed and at index 0. (Using more files, you'll see that this implementation only removes every other file in the array.)
This is why my JavaScript code (above) uses a readIndex and a writeIndex to copy the entries in the array, skipping the readIndex over the indices that are to be deleted. This algorithm avoids the problem of losing correspondence between the array indices. (It does need to be coded carefully to guard against various edge conditions.) I tried some JavaScript code similar to what I wrote above; it worked for me.
I suspect that the problem in your original test case (removing the 2nd file, then adding another) is analogous. Since you've only shown part of your code, I can't tell whether the array indices and the data in listFiles.selectedIndices, arrayQueue, and fileRefList.fileList are always going to match up appropriately. (But I suspect that the problem is that they don't.)
BTW, even if you fix the problem with using splice() by adjusting the array index values appropriately, it's still an O(N2) algorithm in the general case. The array copy algorithm is O(N).
I'd really need to see the whole class to provide a difinitive answer, but I would write a method to handle removing multiple objects from the dataProvider and perhaps assigning a new array as the dataProvider for the list instead of toying with binding and using the same list for the duration. Like I said, this is probably inefficient, and would require a look at the context of the question, but that is what I would do 9unless you have a big need for binding in this circumstance)
/**
* Returns a new Array with the selected objects removed
*/
private function removeSelected(selectedItems:Array):Array
{
var returnArray:Array = []
for each(var object:Object in this.arrayQueue)
{
if( selectedItems.indexOf(object)==-1 )
returnArray.push( object )
}
return returnArray;
}
You might be interested in this blog entry about the fact that robust iterators are missing in the Java language.
The programming language, you mentioned Javascript, is not the issue, it's the concept of robust iterators that I wanted to point out (the paper actually is about C++ as the programming language).
The [research document]() about providing robust iterators for the ET++ C++ framework may still e helpful in solving your problem. I am sure the document can provide you with the necessary ideas how to approach your problem.