0

I have a small problem in finding the most efficient solution. I have a number, for example 10, of student ids. And some of those ids are relative(siblings) to each other. For those who are siblings leave only one of them for identifing, and doesn't matter which, first one is fine.

For example, the student ids

  • original

    1, 2, 3, 4, 5, 6, 7, 8, 9, 10

where 1, 2, 3 are one family siblings, and 8, 9 are another. At the end I should have:

  • expected

    1, 4, 5, 6, 7, 8, 10

I am doing it through loop.


UPDATE:

I just stopped to implement it, because it gets bigger and bigger. This is a big picture of what I have in my mind. I just gathered all sibling ids for each given id row by row, and then I was going to iterate per each. But like I said it's wasting time.

  • Code (in conceptual)

    static string Trimsiblings(string ppl) {
        string[] pids=ppl.Split(',');
        Stack<string> personid=new Stack<string>();
    
        foreach(string pid in pids) {
            // access database and check for all sibling 
            // is for each individual pid 
            // such as in example above 
            // row 1: field 1=1, field2=2, field3=3 
            // row 2: field 1=8, field2=9 
    
            query = Select..where ..id = pid; // this line is pesudo code
    
            for(int i=0; i<query.Length; i++) {
                foreach(string pid in pids) {
                    if(query.field1==pid) {
                        personid.Push(pid);
    
                    }
                }
            }
        }
    }
    
4

2 に答える 2

2

For an efficient code, it essential to notice that the one member (e.g., the first) of each family of siblings is irrelevant because it will stay in the output. That is, we simply have to

  1. Create a list of items that must not appear in the output
  2. Actually remove them

Of course, this only works under the assumption that every sibling actually appears in the original list of ids.

In code:

int[] ids = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int families = new int[2][] {
    new int [] {1, 2, 3},
    new int [] {8, 9}
};
var itemsToOmit = siblings.
    Select(family => family.Skip(1)).
    Aggregate((family1, family2) => family1.Concat(family2));
var cleanedIds = ids.Except(itemsToOmit);

Edit: Since you mention that you are not too familiar with the syntax, I will give some further explanations

  • The expressions I've used are extension methods that are part of the System.LINQ namespace
  • The Select method transforms one sequence into another sequence. Since families is sequence of sequences, family will be a sequence of siblings in the same family (i.e., 1, 2, 3 and 8, 9 in this particular case)
  • The Skip method skips a number of elements of a sequence. Here, I've decided to always skip the first element (for reasons, see above)
  • The Aggregate method combines element of a sequence into a single element. Here, all families of siblings are just concatenated to each other (except for the first sibling of each family which has been omitted via Skip)
  • The Except method returns all elements of a sequence that are not in the sequence that is given as an argument.

I hope this clarifies things a bit.

于 2013-03-19T05:28:18.343 に答える
2

Here's how

public static String Trimsiblings(String ppl) {
    var table=GetSiblingTable();
    var pids=ppl.Split(',');

    return
        String.Join(", ", (
            from id in pids.Select(x => int.Parse(x))
            where (
                from row in table.AsEnumerable()
                select
                    from DataColumn column in table.Columns
                    let data=row[column.ColumnName]
                    where DBNull.Value!=data
                    select int.Parse((String)data)
                ).All(x => false==x.Contains(id)||x.First()==id)
            select id.ToString()).ToArray()
            );
}

// emulation of getting table from database
public static DataTable GetSiblingTable() {
    var dt=new DataTable();

    // define field1, ..., fieldn
    for(int n=3, i=1+n; i-->1; dt.Columns.Add("field"+i))
        ;

    dt.Rows.Add(new object[] { 1, 2, 3 });
    dt.Rows.Add(new object[] { 8, 9 });
    return dt;
}

public static void TestMethod() {
    Console.WriteLine("{0}", Trimsiblings("1, 2, 3, 4, 5, 6, 7, 8, 9, 10"));
}

comment to request why(if you need).

于 2013-03-19T07:55:23.470 に答える