How can i match two different List? - c#

I have 2 GameObject and each other has a lot of child. This two GameObject same as same except some child's exist or child's position. I found each child's name.
And also I found locations info for each item. Then I compared this Lists and i found relocated, exist, added and removed items. I want to match with relocated items with names. How can I do that?
On Project1
List<string> existItems = GetNames().Intersect(revisedBasicProject4.GetNames4()).ToList();
List<Vector3> comparePosition = GetLocations().Except(revisedBasicProject4.GetLocations()).ToList();
foreach (var item in existItems)
{
isExist = true;
}
if (isExist)
{
foreach (var item in comparePosition)
{
Debug.Log("RELOCATED ITEMS :" +item);
}
}

I do not know if I understood what you meant correctly or not, but you can use the following code
List<string> existItems = GetNames().Intersect(revisedBasicProject4.GetNames4()).ToList();
List<Vector3> comparePosition = GetLocations().Except(revisedBasicProject4.GetLocations()).ToList();
foreach (var item in existItems)
foreach (var li in comparePosition)
if (item.(...) == li.(...)) {
Debug.Log("RELOCATED ITEMS :" + item);
}

Following on from https://stackoverflow.com/users/7111561/derhugo and https://stackoverflow.com/users/13922490/mohammad-asadi - You want to store names and locations together, so use Transform:
Then, you can compare your revisedBasicProject4 Transforms with the current class like so:
foreach(var transform in GetTransforms())
{
foreach(var revisedBasicProject4Transform in revisedBasicProject4.GetTransforms())
{
if ( transform.name == revisedBasicProject4Transform.name
&& transform.position != revisedBasicProject4Transform.position)
{
Debug.Log("RELOCATED ITEM : " + transform.name);
}
}
}
If you find this is taking forever (because you have millions of Transforms, you may be able to optimise this by doing the following:
var transforms = new List<Transform>(GetTransforms());
var otherTransforms= new List<Transform>(revisedBasicProject4.GetTransforms());
for(var i = 0; i < transforms.Count; i++)
{
for(var j = 0; j < otherTransforms.Count; j++)
{
if ( transforms[i].name == otherTransforms[j].name )
{
if ( transforms[i].position != otherTransforms[j].position )
Debug.Log("RELOCATED ITEM : " + transforms[i].name);
otherTransforms.RemoveAt(j); //We found it so remove it from our temporary "otherTransforms" list
break; //We found it so move on to the next "transforms" item
}
}
}

Related

How to prevent a child destroying in Unity

I am preparing a puzzle game. I can drag and drop from down generated sticks to up places. Let's say that there are two sticks on the first node and we have 2 more sticks in bottom. We can drag it to right place and make them one parent again. I can make them one parent but second stick from buttom is destroying when i drop on the first node.
In this picture it is aqua color:
before drop
after drop
How to resolve this issue?
if(nodes[smallestId].transform.childCount > 0)
{
for (int i = 0; i < rayhit.transform.childCount; i++)
{
nodes[smallestId].transform.GetChild(0).GetComponent<Node>().sticks.Add(rayhit.transform.GetChild(i).GetComponent<Stick>());
rayhit.transform.GetChild(i).transform.SetParent(nodes[smallestId].transform.GetChild(0));
}
Destroy(rayhit.transform.gameObject);
}
else
{
rayhit.transform.SetParent(nodes[smallestId].transform);
Debug.Log("Stick : " + nodes[smallestId].transform);
}
The issue is that you iterate over rayhit.transform.childCount.
When you remove a child due to rayhit.transform.GetChild(i).transform.SetParent the rayhit.transform.childCount is already reduced by one.
Therefore in the next iteration i might already be greater then rayhit.transform.childCount so e.g. the second object is not moved to the new parent!
Instead You could use
// do this only once
var targetParent = nodes[smallestId].transform;
if(targetParent > 0)
{
targetParent = targetParent.GetChild(0);
// do also this only once
var node = targetParent.GetComponent<Node>();
var toMove = new List<Transform>();
foreach (Transform child in rayhit.transform)
{
node.sticks.Add(child.GetComponent<Stick>());
toMove.Add(child);
}
foreach(var child in toMove)
{
child.SetParent(targetParent);
}
Destroy(rayhit.transform.gameObject);
}
else
{
rayhit.transform.SetParent(targetParent);
Debug.Log("Stick : " + targetParent);
}
Which first stores them all in a list so you don't depend on whether they already where moved to a new parent or not.
As alternative I think you could even rather use GetComponentsInChildren here which would completely save you from the trouble and you wouldn't need to use two loops at all:
var targetParent = nodes[smallestId].transform;
if(targetParent > 0)
{
targetParent = targetParent.GetChild(0);
// do also this only once
var node = targetParent.GetComponent<Node>();
// These references now don't depend on their parent object
// so you can safely iterate on them without any issues
foreach (var stick in rayhit.transform.GetComponentsInChildren<Stick>(true))
{
node.sticks.Add(stick);
stick.transform.SetParent(targetParent);
}
Destroy(rayhit.transform.gameObject);
}
else
{
rayhit.transform.SetParent(targetParent);
Debug.Log("Stick : " + targetParent);
}
guys here is solution :)
rayhit.transform.position = nodes[smallestId].transform.position;
if (rayhit.transform.parent != nodes[smallestId].transform)
{
if (nodes[smallestId].transform.childCount > 0 && nodes[smallestId].transform != rayhit.transform.parent)
{
if (currNode != null)
{
for (int i = 0; i < currNode.sticks.Count; i++)
{
nodes[smallestId].transform.GetChild(0).GetComponent<Node>().sticks.Add(currNode.sticks[i]);
currNode.sticks[i].transform.SetParent(nodes[smallestId].transform.GetChild(0));
}
Destroy(rayhit.transform.gameObject);
}
}
else
{
if (currNode != null)
{
currNode.isMoved = true;
}
rayhit.transform.SetParent(nodes[smallestId].transform);
}
}
Thank you for your help.

Delete Multiple Items from ObservableCollection

I want to delete multiple items in an ObservableCollection in C#. My code is:
var item = (MoveDataModel)e.SelectedItem;
var answer = await DisplayAlert("Confirmation", "Are you sure you wish to delete " + item.value + "?", "Yes", "No");
if (answer)
{
var type = item.type;
var value = item.value;
foreach (var listItem in items)
{
if ((listItem.value == item.value) || (listItem.location == value && type == "Location"))
{
items.Remove(listItem);
itemCount--;
}
}
}
The first iteration works fine. However, it hangs on
foreach (var listItem in items)
on the second pass. I'm not sure how to make it work.
you can't modify a collection while you're iterating over it. Try something like this (I haven't checked the syntax, may need some cleanup)
var removeList = items.Where(x => x.value == value).Where(y => y.type = type).ToList();
foreach(var i in removeList) {
items.Remove(i);
itemCount--;
}
Have your own counter, cycle backwards through the list so you wont have to readjust for indexes you removed.
System.Collections.ObjectModel.ObservableCollection<object> list = new System.Collections.ObjectModel.ObservableCollection<object>();
private void RemoveStuff()
{
var i = list.Count - 1;
for (; i <= 0; i--)
{
// some checks here to make sure this is the time you really want to remove
list.Remove(i);
}
}

remove split lines by index with same value from list

-from the list an example is 9120038560640 occurs twice or could be more than that.
-lines stored in List<.string> items = File.ReadAllLines(filepath).ToList();
-every line is split in semi colon.
-second index or [1] should compare to all of the lines and remove with found matched.
363193;9120038560640;7,11;9,99 <---- must be remove
363195;9120038560641;9,81;14,99
363194;9120038560640;9,81;14,99 <--- must be remove
363196;9120038560642;9,81;14,99
363197;9120038560643;9,81;14,99
....
..
.
btw. my file has 25,000++ items.
thank you
okay i got the answer and this is working
items = items.Where(x => x.Split(';')[columnIndex] != "").OrderBy(x => x.Split(';')[columnIndex]).ToList();
List<.string> _items = items.ConvertAll(z => z); //I make independent copy
string[] itemsArr = items.ToArray();
int countA = 0;
foreach (string itemArr in itemsArr)
{
List<int> groupDuplicates = new List<int>();
for (int a = countA; a < itemsArr.Count(); a++)
{
if (itemArr != itemsArr[a])
{
if (itemArr.Split(';')[columnIndex] == itemsArr[a].Split(';')[columnIndex]) //if matched then add
{
groupDuplicates.Add(a); // listing index to be remove
}
else
break; //no way to go through the bottom of the list and also to make the performance faster
}
countA++;
}
if (groupDuplicates.Count() != 0)
{
groupDuplicates.Add(groupDuplicates.First() - 1); //I add here the first item in duplicates
foreach (int m in groupDuplicates)
{
_items.Remove(items.ElementAt(m)); //remove by item not by index
}
}
}

Check if Listbox contains a certain element

I know this question was posted here already multiple times but I've read the threads and nothing works for me so I decided to ask here.
I simply want to check if a certain string is already in my listbox. I've tried the
listBox.Items.Contains("stringToMatch")
but I get nothing.
I also tried
foreach (var item in form1.filterTypeList.Items)
{
if (item.ToString() == "stringToMatch")
{
break;
}
He doesn't find anything. Why? How can I solve that?
Try using this way... FindByText
strig toMatch = "stringToMatch";
ListItem item = ListBox1.Items.FindByText(toMatch);
if (item != null)
{
//found
}
else
{
//not found
}
Please try like below. I am doing for loop on List view items to search string based on item tag or item text.
for (int i = 0; i <= ListView.Items.Count - 1; i++)
{
itmX = ListView.Items.Item(i);
if (itmX.Text.ToString() = "stringToMatch")
{
break;
}
}
OR
for (int i = 0; i <= ListView.Items.Count - 1; i++)
{
itmX = ListView.Items.Item(i);
if (itmX.Tag.ToString() = "stringToMatch")
{
break;
}
}
its so simple now , you simply first find the index of that item in the collection of listbox items and then use this fuction of listbox listBox1.FindStringExact .
private void FindMySpecificString(string searchString)
{
// Ensure we have a proper string to search for.
if (searchString != string.Empty)
{
// Find the item in the list and store the index to the item.
int index = listBox1.FindStringExact(searchString);
// Determine if a valid index is returned. Select the item if it is valid.
if (index != ListBox.NoMatches)
listBox1.SetSelected(index,true);
else
MessageBox.Show("The search string did not find any items in the ListBox that exactly match the specified search string");
}
}
visit the following website for more clarification and examples
https://msdn.microsoft.com/en-us/en-en/library/81wes5yz(v=vs.110).aspx

Filtering elements of an array

I have an array as
That is, each item has its category in the following index.
I need all the items whose category are TotalNumbers and CurrentNumbers.
I tried
int i = 1;
foreach (string item in statsname)
{
//only number type stats are added to the comboboxes.
if ((statsname[i].ToUpperInvariant()==("TOTALNUMBER")) || ((statsname[i].ToUpperInvariant()==("CURRENTNUMBER"))))
{
comboBox1.Items.Add(statsname[i-1]);
i++;
i++;
}
comboBox1.SelectedIndex = 0;
}
Apparently this does not checks for what I need correctly.
How do I need to modify my codes to get what i need ?
Seems it's better to use a for loop instead of foreach:
for (int i = 1; i < statsname.Length; i += 2)
{
//only number type stats are added to the comboboxes.
if ((statsname[i].ToUpperInvariant()==("TOTALNUMBER")) || ((statsname[i].ToUpperInvariant()==("CURRENTNUMBER"))))
comboBox1.Items.Add(statsname[i-1]);
}
Linq comes to rescue!
var listItems = from s in statsname where s.Equals("TOTALNUMBER", StringComparison.InvariantCultureIgnoreCase) || s.Equals("CURRENTNUMBER", StringComparison.InvariantCultureIgnoreCase) select new ListItem(s);
comboBox1.AddRange(listItems);
Code not tested or compiled, but you can have an idea of what i said.
var filteredValues = Array.FindAll(source, s => s.ToUpperInvariant() == "TOTALNUMBER" ||
s.ToUpperInvariant() == "CURRENTNUMBER").ToList()
I am not sure why you are using index in an foreach loop. The below code should work for you
foreach (string item in statsname)
{
if ( item.ToUpper() == "TOTALNUMBER" || item.ToUpper() == "CURRENTNUMBER")
{
comboBox1.Items.Add(item);
}
}
comboBox1.SelectedIndex = 0;

Categories

Resources