Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
439 views
in Technique[技术] by (71.8m points)

C# SelectMany alternative in Typescript / Javascript

I have a list of projects and each project contains a list of status. I need to find a status with a specific id in all projects.

In C# i can do something like this:

List<StatusResponse> statusList = projects.SelectMany(x => x.Status).ToList();
StatusResponse status = statusList.Find(f => f.Id == id);

I could even do it all in one line:

StatusResponse status = projects.SelectMany(x => x.Status).FirstOrDefault(f => f.Id == id);

In Typescript i do this:

private getStatus(statusId: string): StatusResponse {

    for (let project of this.selectedProjects) {

        let status = project.status.find(find => find.id === statusId);
        if (status)
            return status;
    }

    return null;
}

Question:

Is there simpler solution in Typescript with less code?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You could use flatMap as suggested by @adiga:

// >=ES2019
const status = this.selectedProjects.flatMap(pr => pr.status)
                                    .find(stat => stat.id === statusId);

Alternatively, if your version supports iterators, you could make a reusable generic function like this:

function* selectMany<TIn, TOut>(
    source: Iterable<TIn>,
    selector: (item: TIn) => Iterable<TOut>)
: Iterable<TOut> {
    for (const item of source) {
        const subItems = selector(item);
        for (const subItem of subItems) {
            yield subItem;
        }
    }
}

// and while we are at it. Let's make a FirstOrDefault equivalent.

function firstOrNull<T>(source: Iterable<T>, predicate: (item: T) => boolean): T | null {
    for (const item of source) {
        if (predicate(item)) {
            return item;
        }
    }
    return null;
}

Example usage:

interface Item {
    elements: Array<number>;
}

const items: Item[] = [
    {
        elements: [1, 2, 3]
    },
    {
        elements: [4, 5, 6]
    }
]

const elements = selectMany(items, itm => itm.elements);
for (const el of elements) {
    console.log(el);
}

output:

1
2
3
4
5
6

firstOrNull(elements, itm => itm === 6); // 6
firstOrNull(elements, itm => itm === 7); // null

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...