Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove from String Array what is in List

Tags:

arrays

c#

list

I have a String Array x and a List y and I want to remove all data from Y from the List X, how to do that in the fastest way?

e.g.: X: 1) "aaa.bbb.ccc" 2) "ddd.eee.fff" 3) "ggg.hhh.jjj"

Y: 1) "bbb" 2) "fff"

Result should be a new List in Which only 3) exist because X.1 gets deleted by Y.1 and X.2 gets deleted by Y.2

How to do that?

I know I could do a foreach on the List X and check with everything in List Y, bit is that the fastest way?

like image 918
PassionateDeveloper Avatar asked Oct 23 '13 12:10

PassionateDeveloper


People also ask

What does remove in ArrayList do?

remove(int index) method removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).

How do I remove something from a string in a list Python?

In Python, use list methods clear() , pop() , and remove() to remove items (elements) from a list. It is also possible to delete items using del statement by specifying a position or range with an index or slice.

How remove all string from ArrayList?

textArray. clear(); It will clear whole ArrayList.


2 Answers

The most convenient would be

var Z = X.Where(x => !x.Split('.').Intersect(Y).Any()).ToList();

That is not the same as "fastest". Probably the fastest (runtime) way to do that is to use a token search, like:

public static bool ContainsToken(string value, string token, char delimiter = '.')
{
    if (string.IsNullOrEmpty(token)) return false;
    if (string.IsNullOrEmpty(value)) return false;

    int lastIndex = -1, idx, endIndex = value.Length - token.Length, tokenLength = token.Length;
    while ((idx = value.IndexOf(token, lastIndex + 1)) > lastIndex)
    {
        lastIndex = idx;
        if ((idx == 0 || (value[idx - 1] == delimiter))
            && (idx == endIndex || (value[idx + tokenLength] == delimiter)))
        {
            return true;
        }
    }
    return false;
}

then something like:

var list = new List<string>(X.Length);
foreach(var x in X)
{
    bool found = false;
    foreach(var y in Y)
    {
        if(ContainsToken(x, y, '.'))
        {
            found = true;
            break;
        }
    }
    if (!found) list.Add(x);
}

This:

  • doesn't allocate arrays (for the output of Split, of for the params char[] of Split)
  • doesn't create any new string instances (for the output of Split)
  • doesn't use delegate abstraction
  • doesn't have captured scopes
  • uses the struct custom iterator of List<T> rather than the class iterator of IEnumerable<T>
  • starts the new List<T> with the appropriate worst-case size to avoid reallocations
like image 134
Marc Gravell Avatar answered Oct 18 '22 17:10

Marc Gravell


Iterating over X and Y would indeed be the fastest option because you have this Contains constraint. I really don't see any other way.

It should not be a foreach over X though, because you cannot modify the collection you iterate over with foreach.

So an option would be:

for (int counterX = 0; counterX < X.Length; counterX++)
{
    for(int counterY = 0; counterY < Y.Length; counterY++)
    {
        if (X[counterX].Contains(Y[counterY]))
        {
            X.RemoveAt(counterX--);
            counterY = Y.Length;
        }
    }
}

This should do it (mind you, this code is not tested).

like image 23
Roy Dictus Avatar answered Oct 18 '22 17:10

Roy Dictus